简体   繁体   中英

Is it possible to add a Private Key + Certificate to the KeyChain on Android without a P12?

The following code allows me to add a PKCS12 file to the KeyChain which works great:

val pkcs12Bytes = pkcs12Location.readBytes()
val installIntent = KeyChain.createInstallIntent()
installIntent.putExtra(KeyChain.EXTRA_PKCS12, pkcs12Bytes)
startActivity(installIntent)

However, for security reasons, I wish to add a Private Key and Certificate to the KeyChain without ever storing a P12 on the device. The Private Key is stored in memory after being created by keyGen.generateKeyPair() .

This is the popup that I get when using the P12 implementation (notice "one user key"):

在此处输入图像描述


So far I've been able to add a certificate to the KeyChain with this code

val installIntent = KeyChain.createInstallIntent()
installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, x509Certificate)
startActivity(installIntent)

but I can't find a way to include the Private Key in the documentation . Is it possible to add a Private Key + Certificate to the Keychain on Android without a P12?

This is the popup that I get when using the Certificate implementation (notice only a certificate):

在此处输入图像描述

After getting creative, the answer is kind of .

It doesn't seem to be possible to completely bypass the KeyChain.EXTRA_PKCS12 method, but I did find a way to store the P12 in memory so that it's never stored on the Android's file system. This way is more secure than storing it on the file system, but still not as secure as if we were able to add the private key and certificate directly into the KeyChain .

This is the method that I used to create the PKCS12 in memory instead of on the file system:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public static byte[] createPKCS12InMemory(byte[] x509AsPEM, PrivateKey privKey, String pkcs12Password) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
    InputStream stream = new ByteArrayInputStream(x509AsPEM);
    CertificateFactory fact = CertificateFactory.getInstance("X.509");
    X509Certificate cert = (X509Certificate) fact.generateCertificate(stream);
    KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
    pkcs12.load(null, null);
    pkcs12.setKeyEntry("device_certificate", privKey, pkcs12Password.toCharArray(), new Certificate[] {cert});
    ByteArrayOutputStream p12 = new ByteArrayOutputStream();
    pkcs12.store(p12, pkcs12Password.toCharArray());
    return p12.toByteArray();
}

Once you have the PKCS12 as bytes in memory, you can pass it directly into the installIntent , effectively never storing a p12 on the file system!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM