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/e9da4e0f-737c-4d82-ba73-3351108e5580%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to