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 android-developers+unsubscr...@googlegroups.com.
To post to this group, send email to android-developers@googlegroups.com.
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/6e4e92b6-4056-4db1-aa3f-b56ec50ede22%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to