Hi Alex,
How silly of me, I thought I already commented out the BouncyCastle JCA
provider. That's done now, and yes, this is running on Android 6 and I'm
using the single arg getInstance for Signature.
Now I get another error, stack trace below:
java.security.InvalidKeyException: Keystore operation failed
at android.security.KeyStore.getInvalidKeyException(KeyStore.
java:692)
at android.security.KeyStore.getInvalidKeyException(KeyStore.
java:712)
at android.security.keystore.KeyStoreCryptoOperationUtils.
getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
ensureKeystoreOperationInitialized(AndroidKeyStoreSignatureSpiBase.java:219)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
engineInitSign(AndroidKeyStoreSignatureSpiBase.java:99)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
engineInitSign(AndroidKeyStoreSignatureSpiBase.java:77)
at java.security.Signature$SignatureImpl.engineInitSign(
Signature.java:706)
at java.security.Signature.initSign(Signature.java:357)
at au.com.taylornetworks.tapid.keystoreContentSigner.
getSignature(keystoreContentSigner.java:69)
at org.spongycastle.pkcs.PKCS10CertificationRequestBuilder.build
(PKCS10CertificationRequestBuilder.java:149)
at au.com.taylornetworks.tapid.pkiManager.generateCSR(pkiManager
.java:78)
at au.com.taylornetworks.tapid.MainActivity.createAndShowCSR(
MainActivity.java:42)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.
AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.
java:270)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21153)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(
ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.security.KeyStoreException: Incompatible
padding mode
at android.security.KeyStore.getKeyStoreException(KeyStore.java:
632)
at android.security.KeyStore.getInvalidKeyException(KeyStore.
java:712)
at android.security.keystore.KeyStoreCryptoOperationUtils.
getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
ensureKeystoreOperationInitialized(AndroidKeyStoreSignatureSpiBase.java:219)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
engineInitSign(AndroidKeyStoreSignatureSpiBase.java:99)
at android.security.keystore.AndroidKeyStoreSignatureSpiBase.
engineInitSign(AndroidKeyStoreSignatureSpiBase.java:77)
at java.security.Signature$SignatureImpl.engineInitSign(
Signature.java:706)
at java.security.Signature.initSign(Signature.java:357)
at au.com.taylornetworks.tapid.keystoreContentSigner.
getSignature(keystoreContentSigner.java:69)
at org.spongycastle.pkcs.PKCS10CertificationRequestBuilder.build
(PKCS10CertificationRequestBuilder.java:149)
at au.com.taylornetworks.tapid.pkiManager.generateCSR(pkiManager
.java:78)
at au.com.taylornetworks.tapid.MainActivity.createAndShowCSR(
MainActivity.java:42)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.
AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.
java:270)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21153)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(
ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
On Thursday, February 18, 2016 at 1:06:27 PM UTC+11, Alex Klyubin wrote:
>
> 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/67ade4d5-9572-4206-92ba-4e2f63ac8472%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.