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.