在API 21中生成密钥对时无法生成证书异常

时间:2018-02-07 13:21:30

标签: android security android-5.0-lollipop android-keystore

我一直试图解决这个仅在Android Lollipop(API 21)中发生的异常。我试图寻找其他解决方案,但唯一相关的是Generate KeyPair with KeyPairGeneratorSpec on API < 23,建议的解决方案无效。

我错过了什么吗?谢谢!

这是我在最后一行投掷的代码:

Calendar start = Calendar.getInstance();
                    Calendar end = Calendar.getInstance();
                    end.add(Calendar.YEAR, 30);
                    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(appContext)
                            .setAlias(getSecureSettingsKeyAlias())
                            .setSubject(new X500Principal("CN=" + getSecureSettingsKeyAlias()))
                            .setSerialNumber(BigInteger.TEN)
                            .setStartDate(start.getTime())
                            .setEndDate(end.getTime())
                            .build();
                    KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, AndroidKeyStore);
                    kpg.initialize(spec);
                    kpg.generateKeyPair();

以下是发生的例外情况:

Caused by: java.lang.IllegalStateException: Can't generate certificate
   at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:136)
   at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:276)
   at com.sampleid.sampleid_sdk.common.FileSettingsStorage.getKeystore(FileSettingsStorage.java:302)
   at com.sampleid.sampleid_sdk.common.FileSettingsStorage.writeSecureSettings(FileSettingsStorage.java:185) 
   at com.sampleid.sampleid_sdk.common.SettingsImpl.saveSecureSettings(SettingsImpl.java:473) 
   at com.sampleid.sampleid_sdk.common.SettingsImpl.saveSettings(SettingsImpl.java:321) 
   at com.sampleid.sampleid_sdk.sampleIDService.saveSettingsToStorage(sampleIDService.java:102) 
   at com.sampleid.sampleid_sdk.sampleIDService.saveSettings(sampleIDService.java:91) 
   at com.sampleid.sampleid.features.shared.BaseActivity.onStop(BaseActivity.java:182) 
   at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1261) 
   at android.app.Activity.performStop(Activity.java:6089) 
   at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3341) 
   at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3390) 
   at android.app.ActivityThread.access$1100(ActivityThread.java:144) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:135) 
   at android.app.ActivityThread.main(ActivityThread.java:5221) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:372) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
Caused by: java.lang.UnsupportedOperationException: private exponent cannot be extracted
   at com.android.org.conscrypt.OpenSSLRSAPrivateKey.getPrivateExponent(OpenSSLRSAPrivateKey.java:161)
   at org.spongycastle.jcajce.provider.asymmetric.rsa.RSAUtil.generatePrivateKeyParameter(RSAUtil.java:63)
   at org.spongycastle.jcajce.provider.asymmetric.rsa.DigestSignatureSpi.engineInitSign(DigestSignatureSpi.java:95)
   at java.security.Signature$SignatureImpl.engineInitSign(Signature.java:679)
   at java.security.Signature.initSign(Signature.java:330)
   at com.android.org.bouncycastle.x509.X509Util.calculateSignature(X509Util.java:243)
   at com.android.org.bouncycastle.x509.X509V3CertificateGenerator.generate(X509V3CertificateGenerator.java:434)
   at com.android.org.bouncycastle.x509.X509V3CertificateGenerator.generate(X509V3CertificateGenerator.java:412)
   at android.security.AndroidKeyPairGenerator.generateKeyPair(AndroidKeyPairGenerator.java:133)
   at java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair(KeyPairGenerator.java:276) 
   at com.sampleid.sampleid_sdk.common.FileSettingsStorage.getKeystore(FileSettingsStorage.java:302) 
   at com.sampleid.sampleid_sdk.common.FileSettingsStorage.writeSecureSettings(FileSettingsStorage.java:185) 
   at com.sampleid.sampleid_sdk.common.SettingsImpl.saveSecureSettings(SettingsImpl.java:473) 
   at com.sampleid.sampleid_sdk.common.SettingsImpl.saveSettings(SettingsImpl.java:321) 
   at com.sampleid.sampleid_sdk.sampleIDService.saveSettingsToStorage(sampleIDService.java:102) 
   at com.sampleid.sampleid_sdk.sampleIDService.saveSettings(sampleIDService.java:91) 
   at com.sampleid.sampleid.features.shared.BaseActivity.onStop(BaseActivity.java:182) 
   at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1261) 
   at android.app.Activity.performStop(Activity.java:6089) 
   at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3341) 
   at android.app.ActivityThread.handleStopActivity(ActivityThread.java:3390) 
   at android.app.ActivityThread.access$1100(ActivityThread.java:144) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:135) 
   at android.app.ActivityThread.main(ActivityThread.java:5221) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at java.lang.reflect.Method.invoke(Method.java:372) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

1 个答案:

答案 0 :(得分:1)

终于能够解决这个问题。问题出在以下方面:

KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, AndroidKeyStore);

KeyProperties.KEY_ALGORITHM_RSA仅从API 23开始可用,因此在此之前在API中会失败。将其替换为“ RSA”

此外,如果您使用的是SpongyCastle,则应使用以下方法添加它:

static {
        // as per https://github.com/rtyley/spongycastle/issues/27
        Security.addProvider(new org.spongycastle.jce.provider.BouncyCastleProvider());
    }