2016-11-05 107 views
6

我正在开发一个Android项目。在Android中安装PEM证书的正确方法

我有一个PEM证书字符串:

-----BEGIN CERTIFICATE----- 
MIIEczCCA1ugAwIBAgIBADANBgkqhkiG9w0BAQQFAD..AkGA1UEBhMCR0Ix 
EzARBgNVBAgTClNvbWUtU3RhdGUxFDASBgNVBAoTC0..0EgTHRkMTcwNQYD 
VQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcn..XRpb24gQXV0aG9y 
...MANY LINES... 
It8una2gY4l2O//on88r5IWJlm1L0oA8e4fR2yrBHX..adsGeFKkyNrwGi/ 
7vQMfXdGsRrXNGRGnX+vWDZ3/zWI0joDtCkNnqEpVn..HoX 
-----END CERTIFICATE----- 

(以上证书字符串指定给名为CERT_STR一个变量)

我解码上述PEM字符串字节数组:

byte[] pemBytes = Base64.decode(
       CERT_STR.replaceAll("-----(BEGIN|END) CERTIFICATE-----", "") 
         .replaceAll("\n", "") 
         .getBytes("UTF-8"), 
       Base64.DEFAULT 
     ); 

我尝试通过以下代码以编程方式将PEM证书安装到我的Android手机:

Intent intent = KeyChain.createInstallIntent(); 
// because my PEM only contains a certificate, no private key, so I use EXTRA_CERTIFICATE 
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, pemBytes);// above PEM bytes 
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
context.startActivity(intent); 

当我的代码运行(在Android的7设备),Android系统的证书安装程序弹出的窗口,当我按下“OK”该窗口的按钮,我得到了以下日志:

java.io.IOException: stream does not represent a PKCS12 key store 
    at com.android.org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.engineLoad(PKCS12KeyStoreSpi.java:793) 
    at java.security.KeyStore.load(KeyStore.java:1247) 
    at com.android.certinstaller.CredentialHelper.loadPkcs12Internal(CredentialHelper.java:396) 
    at com.android.certinstaller.CredentialHelper.extractPkcs12Internal(CredentialHelper.java:364) 
    at com.android.certinstaller.CredentialHelper.extractPkcs12(CredentialHelper.java:354) 
    at com.android.certinstaller.CertInstaller$1.doInBackground(CertInstaller.java:328) 
    at com.android.certinstaller.CertInstaller$1.doInBackground(CertInstaller.java:327) 

我的问题:

  1. 我用EXTRA_CERTIFICATE &将其设置为intent,我没有使用EXTRA_PKCS12,但是从日志中,Android的SY stem认为我正在安装PKCS#12密钥存储库。为什么?

  2. 在Android中以编程方式安装PEM证书的正确方法是什么?

+0

'流不代表PKCS12关键store'任何理由不尝试将其转换到PKCS12呢? –

+0

但我仍然想知道在Android中安装PEM的正确方法是什么,这是我的问题。 –

+0

这似乎是完全重复的https://stackoverflow.com/questions/40464815/install-x509-certificate-programmatically-in-my-case – ozbek

回答

0

您的代码应该如@Sergey Nikitin所说的那样工作。焦点复制example Github使用类似的代码

我已阅读并通过CredentialHelperCertInstaller的Android 7.1源代码来跟踪您的异常日志。独特的可到达路径在

com.android.certinstaller.CredentialHelper.extractPkcs12(CredentialHelper.java:354) 

执行pkcs12装载机是由CredentialHelper.hasPkcs12KeyStore()

boolean hasPkcs12KeyStore() { 
    return mBundle.containsKey(KeyChain.EXTRA_PKCS12); 
} 

我还没有发现默认分配的值或可替代的路径保护的方法onScreenlockOk

private void onScreenlockOk() { 
    if (mCredentials.hasPkcs12KeyStore()) { 
     if (mCredentials.hasPassword()) { 
      showDialog(PKCS12_PASSWORD_DIALOG); 
     } else { 
      new Pkcs12ExtractAction("").run(this); 
     } 

,所以我推断KeyChain.EXTRA_PKCS12正在以某种方式使用。这是一个奇怪的行为,可能是你有一个干净的&重建问题?

我建议调试包括Android CertInstaller类的代码,以确保额外的价值,并确保执行的代码是预期