在API级别< 23上通过KeyStore生成椭圆曲线KeyPair

时间:2018-05-02 08:40:25

标签: android android-keystore elliptic-curve

我需要在Android中生成一个椭圆密钥对,并将其存储到KeyStore以保护私钥不被提取。

我能够使用Spongycastle库生成密钥对,但我无法在KeyStore中导入密钥对。首先,因为我没有证书,其次,即使我尝试创建证书,也没有导入密钥。

我使用KeyGenParameterSpec生成密钥对,但在版本23以下的API中无法访问。

总结一下我的问题,是否有一种非黑客的方式如何使用通用的Android资源?或者根本不可能在版本Lollipop上使用椭圆曲线键并降低?

2 个答案:

答案 0 :(得分:4)

Android keystore system的文档是section on supported key generation algorithms。它声明:

  

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

如果您可以忍受这些限制,那么您可以将Android Keystore用于API级别,直至API 19.看起来您可以使用API​​ 18,但是设置密钥大小和密钥类型的必要方法可以在API级别19之前不存在。用于构建API级别19到22的参数规范的类的名称是KeyPairGeneratorSpec.Builder。这与用于API级别23及更高级别的类KeyGenParameterSpec.Builder非常相似,所以请注意不要混淆两者。

以下是一小段代码,说明了上述内容。它应该在API 19上运行。

private void createEcKey() throws Exception {
    Calendar start = Calendar.getInstance();
    Calendar end = Calendar.getInstance();
    end.add(Calendar.YEAR, 1);
    KeyPairGeneratorSpec spec =
            new KeyPairGeneratorSpec.Builder(this)
                    .setAlias("myKey")
                    .setKeySize(256)
                    .setKeyType("EC")
                    .setSubject(new X500Principal("CN=Dodgy Stuff"))
                    .setSerialNumber(BigInteger.valueOf(123456789L))
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .build();
    KeyPairGenerator kpg = KeyPairGenerator.getInstance(
            "RSA", "AndroidKeyStore");
    kpg.initialize(spec);
    KeyPair keyPair = kpg.generateKeyPair();
    ECPublicKey ecPublicKey = (ECPublicKey) keyPair.getPublic();
    ECPrivateKey ecPrivateKey = (ECPrivateKey) keyPair.getPrivate();

    //
    // The following will throw an Exception if uncommented, because
    //    the private key is not allowed to leave the protection of
    //    the Androud Keystore boundary.
    //
    // byte [] privEncoded = ecPrivateKey.getEncoded();
}

答案 1 :(得分:0)

生成secp256r1密钥对代码:

val kpg: KeyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore")
val parameterSpec = KeyGenParameterSpec.Builder("container", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setAlgorithmParameterSpec(ECGenParameterSpec("secp256r1"))
                .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA512)
                .build()
kpg.initialize(parameterSpec)
val keyPair = kpg.generateKeyPair()

val ecPublicKey = keyPair.public as ECPublicKey
val ecPrivateKey = keyPair.private as ECPrivateKey