使用AndroidKeyStore <Api23生成EC密钥对

时间:2019-07-15 15:15:57

标签: android android-keystore android-security

无法使用AndroidKeystore提供程序之一

根据AndroidKeyStore documentation

  

在API级别23之前,可以使用算法“ RSA”初始化的KeyPairGeneratorSpec的KeyPairGenerator生成EC密钥,该算法的密钥类型使用setKeyType(String)设置为“ EC”。无法使用此方法指定EC曲线名称-根据请求的键大小自动选择NIST P曲线。

在Api 23以下,我应该能够使用AndroidKeyStore提供程序生成EC密钥对,如下所示,这是我目前正在执行的代码段。

val ecGenParameterSpec = ECGenParameterSpec("P-256")
val spec = KeyPairGeneratorSpec.Builder(context)
                .setAlias(ALIAS)
                .setSubject(X500Principal("CN=example"))
                .setSerialNumber(BigInteger.ONE)
                .setKeyType("EC")
                .setAlgorithmParameterSpec(ecGenParameterSpec)
                .setStartDate(start)
                .setEndDate(end)
                .build()
                val keyGen = KeyPairGenerator.getInstance("RSA", androidKeyStoreProvider)
keyGen.initialize(spec, SecureRandom())
keyGen.generateKeyPair()

但是我不断得到java.lang.UnsupportedOperationException: private key value S cannot be extracted

在使用AndroidKeyStore生成EC密钥对期间,我做错什么了吗?

还是我误解了KeyPairGenerator的官方AndroidKeyStore documentation

下面是我尝试过的其中一种设备(oneplus之一)的堆栈跟踪。 我已经在api 21和22的多种设备上尝试过。

设备-Asus zenfone2(api21),nexus 4(api22),oneplus one(api22),redmi note2(api21)

No pending exception expected: java.lang.UnsupportedOperationException: private key value S cannot be extracted
  at java.math.BigInteger com.android.org.conscrypt.OpenSSLECPrivateKey.getS() (OpenSSLECPrivateKey.java:141)
  at com.android.org.bouncycastle.crypto.params.AsymmetricKeyParameter com.android.org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.gen
   eratePrivateKeyParameter(java.security.PrivateKey) (ECUtil.java:188)
  at void com.android.org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi.engineInitSign(java.security.PrivateKey) (SignatureSpi.java:
   61)
  at void java.security.Signature$SignatureImpl.engineInitSign(java.security.PrivateKey) (Signature.java:679)
  at void java.security.Signature.initSign(java.security.PrivateKey) (Signature.java:330)
  at byte[] org.conscrypt.CryptoUpcalls.signDigestWithPrivateKey(java.security.PrivateKey, byte[], java.lang.String) (SourceFile:101)
  at byte[] org.conscrypt.CryptoUpcalls.ecSignDigestWithPrivateKey(java.security.PrivateKey, byte[]) (SourceFile:67)
  at byte[] org.conscrypt.NativeCrypto.EVP_DigestSignFinal(org.conscrypt.NativeRef$EVP_MD_CTX) (SourceFile:-2)
  at byte[] org.conscrypt.OpenSSLSignature.engineSign() (SourceFile:226)
  at byte[] java.security.Signature$SignatureImpl.engineSign() (Signature.java:659)
  at byte[] java.security.Signature.sign() (Signature.java:368)
  at byte[] com.android.org.bouncycastle.x509.X509Util.calculateSignature(com.android.org.bouncycastle.asn1.DERObjectIdentifier, java.lang.Str
   ing, java.security.PrivateKey, java.security.SecureRandom, com.android.org.bouncycastle.asn1.ASN1Encodable) (X509Util.java:248)
  at java.security.cert.X509Certificate com.android.org.bouncycastle.x509.X509V3CertificateGenerator.generate(java.security.PrivateKey, java.s
   ecurity.SecureRandom) (X509V3CertificateGenerator.java:434)
  at java.security.cert.X509Certificate com.android.org.bouncycastle.x509.X509V3CertificateGenerator.generate(java.security.PrivateKey) (X509V
   3CertificateGenerator.java:412)
  at java.security.KeyPair android.security.AndroidKeyPairGenerator.generateKeyPair() (AndroidKeyPairGenerator.java:133)
  at java.security.KeyPair java.security.KeyPairGenerator$KeyPairGeneratorImpl.generateKeyPair() (KeyPairGenerator.java:276)

更新

发现了问题,我在应用程序中使用的是Google Conscrypt Android

Security.insertProviderAt(Conscrypt.newProvider(), 1)

当我在应用程序中使用Conscrypt提供程序时,AndroidKeyStore无法生成EC密钥对。 取消使用Conscrypt似乎可以解决问题。

1 个答案:

答案 0 :(得分:0)

我建议避免在棉花糖(API级别23)之前的设备上使用AndroidKeyStore。在棉花糖之前,AndroidKeyStore非常不可靠。有关详情,请参见this blog post。从棉花糖上来说很好。.但是不要使用setEncryptionRequired(true),它没有任何用处,并且会引起一些问题。

(我是拥有AndroidKeyStore的Google工程师。)