P. S. Typo: bcProviderIndex = i; should be bcProviderIndex = i + 1; Security.insertProviderAt uses a 1-based indexing scheme...
Alex On Wednesday, February 17, 2016 at 6:02:04 PM UTC-8, Alex Klyubin wrote: > > Oh, I didn't notice the PkiManager class in OP. It does install Bouncy > Castle as the highest-priority JCA Provider. Unfortunately, Bouncy Castle > JCA Provider has a bug (http://www.bouncycastle.org/jira/browse/BJA-543 > <https://www.google.com/url?q=http://www.bouncycastle.org/jira/browse/BJA-543&sa=D&usg=AFQjCNEErNOODYZHHZomGgR1y7NLq2yegw>) > > where is advertises to JCA that it can handle any keys, even those that it > actually can't handle, such as Android Keystore keys which don't expose > private/secret key material. Here are some options to work around this > issue: > 1. Don't install the Bouncy Castle JCA Provider if you don't need to. For > example, you don't need it for crypto operations involving Android Keystore > keys. > 2. If you must install the Bouncy Castle JCA Provider, install it below > Android Keystore JCA provider. The best way to achieve that is to find the > index at which the platform-bundled Bouncy Castle provider is installed, > and then invoke Security.insertProviderAt with that same index and your > Bouncy Castle Provider. This will install your Bouncy Castle provider just > above the preinstalled Bouncy Castle provider which is itself installed at > the correct spot for Android Keystore stuff to work. For example: > > Provider[] providers = Security.getProviders(); > int bcProviderIndex = -1; > for (int i = 0; i < providers.length; i++) { > Provider provider = providers[i]; > if ("BC".equals(provider.getName())) { > bcProviderIndex = i; > break; > } > } > Security.insertProviderAt(new BouncyCastleProvider(), > bcProviderPosition); > > Alex > > On Wednesday, February 17, 2016 at 5:41:40 PM UTC-8, Alex Klyubin wrote: >> >> * Please provide the full stack trace (at least from Signature.initSign >> down into the framework). >> * What version of Android is this (e.g., 6.0)? >> * Are you installing any additional JCA providers (e.g., >> Security.insertProviderAt or Security.addProvider)? >> * Please confirm that you're not specifying a provider when invoking >> Signature.getInstance. (i.e., that you're using the single-arg getInstance, >> not the one that takes an additional String or Provider argument). >> >> Cheers, >> Alex >> >> On Wednesday, February 17, 2016 at 5:25:34 PM UTC-8, Jacob Taylor wrote: >>> >>> Hey Alex, >>> >>> When I input PrivateKey object from entry.getPrivateKey() to >>> s.initSign(), the following exception occurs: >>> >>> java.security.InvalidKeyException: Supplied key >>> (android.security.keystore.AndroidKeyStoreRSAPrivateKey) is not a >>> RSAPrivateKey instance. >>> >>> This is the new code: >>> Signature s = Signature.getInstance(algorithmText); >>> KeyStore.Entry entry = ks.getEntry(keyAlias, null); >>> PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey >>> (); >>> >>> s.initSign(privateKey); // <--- excepts here >>> >>> >>> For the time being, algorithmText is set to "SHA512withRSA". >>> >>> Cheers, >>> Jake >>> >>> >>> >>> On Thursday, February 18, 2016 at 6:06:15 AM UTC+11, Alex Klyubin wrote: >>>> >>>> Short answer: Drop the cast to RSAPrivateKey. Use entry.getPrivateKey() >>>> instead. >>>> >>>> Longer answer: RSAPrivateKey interface is for private keys which expose >>>> their key material in a structured way (e.g., expose their private >>>> exponent). Android Keystore keys by definition do not expose their key >>>> material. Thus, Android Keystore private keys are not instances of >>>> RSAPrivateKey. They are instance of PrivateKey and RSAKey (this one lets >>>> you obtain the modulus). Signature.initSign happily takes a PrivateKey >>>> instance. Thus, drop the cast to RSAPrivateKey and it'll work just fine. >>>> >>>> On Wednesday, February 17, 2016 at 6:43:04 AM UTC-8, Jacob Taylor wrote: >>>>> >>>>> Hey devs, >>>>> >>>>> I'm working on a proof of concept app for generating an RSA keypair in >>>>> an app, generating a X509 CSR based on the new keypair, then exporting it >>>>> to be signed by some CA. >>>>> As a part o f the CSR generation process the whole CSR must be signed >>>>> by the key itself. >>>>> >>>>> I've been following along with the Keystore page on the documentation >>>>> site ( >>>>> http://developer.android.com/training/articles/keystore.html#SigningAndVerifyingData) >>>>> >>>>> and reached a snag. >>>>> The generation of the CSR is handled by spongycastle, which in turn >>>>> uses a custom build class (called keystoreContentSigner) to sign the >>>>> completed CSR with the keys stored in the keystore. >>>>> According to the above referenced documentation, the call to >>>>> ks.getEntry(keyAlias, null) should return an object typecasted to the >>>>> Keystore.Entry class, which you then cast into a PrivateKeyEntry which >>>>> you >>>>> then call against using its .getPrivateKey method. >>>>> >>>>> On my test phone (Nexus 6P) this flow doesn't work. It excepts during >>>>> the call to initSign, and reports the type of the object return from >>>>> ks.getEntry as android.security.keystore.AndroidKeyStoreRSAPrivateKey, >>>>> which isn't referenced anywhere I can find. >>>>> >>>>> This type can't be casted to anything usable in the current format, is >>>>> there some new way to perform cryptographic operations in Marshmallow, or >>>>> is there something I'm missing? >>>>> >>>>> KeystoreContentSigner class: >>>>> >>>>> package au.com.taylornetworks.tapid; >>>>> >>>>> >>>>> import org.spongycastle.asn1.x509.AlgorithmIdentifier; >>>>> import org.spongycastle.operator.ContentSigner; >>>>> import >>>>> org.spongycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; >>>>> >>>>> import java.io.ByteArrayOutputStream; >>>>> import java.io.OutputStream; >>>>> import java.security.KeyStore; >>>>> import java.security.Signature; >>>>> import java.security.interfaces.RSAPrivateKey; >>>>> >>>>> >>>>> public class keystoreContentSigner implements ContentSigner{ >>>>> >>>>> private AlgorithmIdentifier algorithmIdentifier; >>>>> private String algorithmText; >>>>> private ByteArrayOutputStream dataStream; >>>>> private String keyAlias; >>>>> >>>>> public keystoreContentSigner(String keyAlias) >>>>> { >>>>> algorithmText = "SHA512withRSA"; >>>>> algorithmIdentifier = new >>>>> DefaultSignatureAlgorithmIdentifierFinder().find(algorithmText); >>>>> dataStream = new ByteArrayOutputStream(); >>>>> this.keyAlias = keyAlias; >>>>> } >>>>> >>>>> public void setAlgorithm(String algorithmText) >>>>> { >>>>> this.algorithmText = algorithmText; >>>>> algorithmIdentifier = new >>>>> DefaultSignatureAlgorithmIdentifierFinder().find(algorithmText); >>>>> } >>>>> >>>>> @Override >>>>> public OutputStream getOutputStream() >>>>> { >>>>> return dataStream; >>>>> } >>>>> >>>>> @Override >>>>> public AlgorithmIdentifier getAlgorithmIdentifier() >>>>> { >>>>> return algorithmIdentifier; >>>>> } >>>>> >>>>> public byte[] getSignature() >>>>> { >>>>> byte[] data; >>>>> byte[] signature = null; >>>>> KeyStore ks; >>>>> >>>>> try { >>>>> ks = KeyStore.getInstance("AndroidKeyStore"); >>>>> ks.load(null); >>>>> >>>>> data = dataStream.toByteArray(); >>>>> dataStream.flush(); >>>>> >>>>> Signature s = Signature.getInstance(algorithmText); >>>>> KeyStore.Entry entry = ks.getEntry(keyAlias, null); >>>>> >>>>> s.initSign((RSAPrivateKey) entry); >>>>> s.update(data); >>>>> signature = s.sign(); >>>>> } catch (Exception e) { >>>>> e.printStackTrace(); >>>>> } >>>>> >>>>> return signature; >>>>> } >>>>> >>>>> } >>>>> >>>>> >>>>> PkiManager class: >>>>> Enter >>>>> >>>>> package au.com.taylornetworks.tapid; >>>>> >>>>> import android.security.keystore.*; >>>>> >>>>> import java.io.IOException; >>>>> import java.security.*; >>>>> import java.security.cert.CertificateException; >>>>> import org.spongycastle.asn1.misc.MiscObjectIdentifiers; >>>>> import org.spongycastle.asn1.misc.NetscapeCertType; >>>>> import org.spongycastle.asn1.x500.X500Name; >>>>> import org.spongycastle.asn1.x509.BasicConstraints; >>>>> import org.spongycastle.asn1.x509.ExtendedKeyUsage; >>>>> import org.spongycastle.asn1.x509.Extension; >>>>> import org.spongycastle.asn1.x509.ExtensionsGenerator; >>>>> >>>>> ... >>>> >>>> -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/android-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/android-developers/726b037a-e13a-4c9e-80f8-089c3aa6a205%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.

