我正在尝试编写一个应用程序,使用户能够通过蓝牙/ NFC交换他们的公共(例如RSA)密钥。要存储并稍后检索密钥,我想使用Android's KeyChain API.
到目前为止,我已阅读了在线API文档和一些教程/示例。它们都涉及从PKCS12文件导入密钥链,该文件包含私钥以及相应的公钥和证书。导入此文件后,将返回alias-String以供后续引用。到目前为止,非常好。
但是,我想要做的是接收某人的公钥,存储它,获取别名,在别处存储别名(例如联系人数据)并在用户想要加密消息时使用它来检索公钥那个人那可能吗?我对公钥加密的经验很少,并且觉得我误解了KeyChain API的整个目的。
任何帮助都会受到很多关注!感谢。
答案 0 :(得分:1)
Android KeyChain API旨在存储SSL证书和密钥:安装PKCS#12或受信任的根证书颁发机构证书时自己的密钥。然后,此密钥和证书可供所有应用程序使用。
这取决于您正在开发的应用程序的目的,但您可能应该考虑使用专用于您的应用程序的KeyStore来存储您收到的密钥而不是KeyChain API。
API(KeyStore和KeyChain)的另一个限制是无法直接存储公钥。你需要有证书。我建议您在应用程序中嵌入自签名证书,并使用此证书签署包含应用程序将收到的公钥的“虚拟”证书。
带有bouncycastle库的简化代码片段,用于存储公共RSA密钥:
public void storeRSAPublicKey(String alias, BigInteger modulus, BigInteger exponent)
{
/** Load the key to generate the certificate */
KeyStore ks = getApplicationKeyStore();
KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry)ks.getEntry(MY_PRIVATE_KEY, null);
X509Certificate issuerCert = (X509Certificate)entry.getCertificate();
PrivateKey skey = entry.getPrivateKey();
/** Prepare the certificate template */
RSAKeyParameters params = new RSAKeyParameters(false, modulus, exponent);
SubjectPublicKeyInfo pkInfo = SubjectPublicKeyInfoFactory.SubjectPublicKeyInfo(params);
X500Name issuer = new X500Name(issuerCert.getIssuerX500Principal().getName());
X500Name subject = new X500Name("CN=alias");
X509v3CertificateBuilder builder = new X509v3CertificateBuilder(issuer, randomSeriaNumber(), new Date(), dateIn20years(), subject, pkInfo);
/** Generate the certificate */
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");
ContentSigner signer = csBuilder.build(skey);
X509CertificateHolder holder = builder.build(signer);
/** Store the certificate in the KeyStore */
JcaX509CertificateConverter conv = new JcaX509CertificateConverter();
X509Certificate cert = conv.getCertificate(holder);
ks.setCertificateEntry(alias, cert);
pushKeyStoreToPersistentStorage(ks);
现在您可以使用ks.getCertificateEntry(alias);
请注意,我省略了一些非基本代码,如序列号生成和非日期计算。
您可以使用keytool
创建初始KeyStore,并将其作为资源添加到您的应用中。