I'm currently developing an Android app that generates an RSA key pair, builds and sends an PKCS#10 certification request to one CA, waits for the CA's response (which contains the certificate-chain including the issued for the end-entity), and then builds the PKCS#12 KeyStore to be installed within the Android KeyStore.
I just show you below some piece of code:
// It removes Android-BC
Security.removeProvider("BC");
// I've tried with SpongyCastle but it also fails.
// I've previously imported BC jars.
Security.addProvider(new BouncyCastleProvider());
KeyStore ks = KeyStore.getInstance("PKCS12","BC");
ks.load(null);
// KeyPair generated by RSA with BC, and certificates obtained from CA.
PrivateKey prvK;
Certificate eeCert, caCert;
PKCS12BagAttributeCarrier caCertBagAttr =
(PKCS12BagAttributeCarrier) caCert;
caCertBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("CA"));
PKCS12BagAttributeCarrier certBagAttr =
(PKCS12BagAttributeCarrier) eeCert;
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate"));
certBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
Certificate[] chain = new Certificate[2];
chain[1] = caCert;
chain[0] = eeCert;
PKCS12BagAttributeCarrier privBagAttr =
(PKCS12BagAttributeCarrier) prvK;
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
new DERBMPString("EE Certificate Key"));
privBagAttr.setBagAttribute(
PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
new SubjectKeyIdentifierStructure(eeCert.getPublicKey()));
// Finally, keystore is saved to file.
ks.setKeyEntry("P12", prvK, null, chain);
saveP12File(ks);
The thing is that everything is working OK when I run it on my Windows PC (BouncyCastle 1.49), but that PKCS#12 file created when I run it on Android cannot be used on SSL handshake or signing because Logcat says that it doesn't have any associated PrivateKey.
If I print the full content of the KeyStore on Java after loading the file, it seems that everything is right, but when I use on Android Browser or when I take it and install on Windows, its private key can't be used.
Same code on Android and PC, same version of BC, PKCS#12 doesn't seem to be malformed.
Can anybody help me? Thanks in advance.
EDIT
I have built a servlet that generates an RSA Key Pair and sends back to my app in PEM format. All seems work OK:
- I can generate a valid (encrypting with public and decrypting test works good) RSA keypair either on Android device or through the external servlet.
- I receive both CA and EE certificates from the CA.
- I'm able to build a "valid" PKCS12 (I called it valid because it can be read by Android, Windows)
But:
- I'm not able to open an SSL channel using the EE certificate as client-certificate for handshake. Either on Windows or Android.
I have uploaded to my Dropbox:
- CA certificate
- EE certificate issued by the CA
- Private Key for the EE certificate
- Public Key for the EE certificate
- PKCS12 created on Android
- Java Android Code
Tested against Tomcat with empty trustStore (doesnt' matter which CA issued client-certificate) unsuccessfully.
Does anybody see something that could explain it?