英文:
Is it possible to add a Private Key + Certificate to the KeyChain on Android without a P12?
问题
以下代码允许我将PKCS12文件添加到KeyChain
,效果非常好:
val pkcs12Bytes = pkcs12Location.readBytes()
val installIntent = KeyChain.createInstallIntent()
installIntent.putExtra(KeyChain.EXTRA_PKCS12, pkcs12Bytes)
startActivity(installIntent)
然而,出于安全原因,我希望在不将P12文件存储在设备上的情况下将私钥和证书添加到KeyChain
。私钥在通过keyGen.generateKeyPair()
创建后存储在内存中。
这是在使用P12实现时我收到的弹出窗口(请注意“one user key”):
到目前为止,我已经成功使用以下代码将证书添加到KeyChain
:
val installIntent = KeyChain.createInstallIntent()
installIntent.putExtra(KeyChain.EXTRA_CERTIFICATE, x509Certificate)
startActivity(installIntent)
但是我无法在文档中找到一种方法来包含私钥。在Android上是否有可能在不使用P12的情况下将私钥和证书添加到Keychain?
这是在使用证书实现时我收到的弹出窗口(请注意仅有证书):
英文:
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):
答案1
得分: 1
在创意发挥之后,答案是 有点。
似乎无法完全绕过 KeyChain.EXTRA_PKCS12
方法,但我找到了一种方法将 P12 存储在内存中,从而不会存储在 Android 文件系统中。这种方式比将其存储在文件系统上更安全,但仍然不像如果我们能够直接将私钥和证书添加到 KeyChain
中那样安全。
这是我用来在内存中创建 PKCS12 而不是在文件系统上创建的方法:
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();
}
一旦你将 PKCS12 作为字节存储在内存中,你可以直接将其传递给 installIntent
,从而有效地不在文件系统上存储 p12!
英文:
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!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论