【问题标题】:Generate EC keypair using AndroidKeyStore < Api23使用 Android KeyStore < Api 23 生成 EC 密钥对
【发布时间】:2019-07-15 15:15:57
【问题描述】:

无法使用 AndroidKeystore 提供程序一

根据AndroidKeyStore documentation

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

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

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 密钥对的过程中我做错了吗?

还是我将官方的AndroidKeyStore documentation 误解为KeyPairGenerator

下面是我尝试使用的设备之一(一加一)的堆栈跟踪。 我在 api 21 和 22 上尝试过多个设备。

设备 - 华硕 zenfone2 (api21)、nexus 4(api22)、一加一(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 似乎可以解决问题。

【问题讨论】:

    标签: android android-keystore android-security


    【解决方案1】:

    我建议在 Marshmallow(API 级别 23)之前的设备上避免使用 AndroidKeyStore。在 Marshmallow 之前,AndroidKeyStore 非常不可靠。有关详细信息,请参阅this blog post。从 Marshmallow 开始,这很好.. 但不要使用 setEncryptionRequired(true),它没有任何用处并会导致一些问题。

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

    【讨论】: