ECDH using Android KeyStore generated private key

2019-05-17 06:57发布

问题:

I'm trying to implement ECDH in Android using a private generated by Android KeyStore Provider.

public byte[] ecdh(PublicKey otherPubKey) throws Exception {

    try {
        ECPublicKey ecPubKey = (ECPublicKey) otherPubKey;
        KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
        PrivateKey pk = (PrivateKey) LoadPrivateKey("Backend");
        keyAgreement.init(pk);
        keyAgreement.doPhase(ecPubKey, true);

        return (keyAgreement.generateSecret());
    }
    catch (Exception e)
    {
        Log.e("failure", e.toString());
        return null;
    }
}

However, this exception is catched in keyAgreement.init(pk) :

E/failure: java.security.InvalidKeyException: cannot identify EC private key: java.security.InvalidKeyException: no encoding for EC private key

I generated before successfully the "Backend" Public/Private key pair using:

public void GenerateNewKeyPair(String alias)
        throws Exception {

    if (!keyStore.containsAlias(alias)) {
        // use the Android keystore
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, ANDROID_KEYSTORE);
        keyGen.initialize(
                new KeyGenParameterSpec.Builder(
                        alias,
                        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                        .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
                        .setDigests(KeyProperties.DIGEST_SHA256,
                                KeyProperties.DIGEST_SHA384,
                                KeyProperties.DIGEST_SHA512)
                        .setRandomizedEncryptionRequired(true)
                        .build());
        // generates the keypair
        KeyPair keyPair = keyGen.generateKeyPair();
    }

}

And I load the private key using:

public PrivateKey LoadPrivateKey(String alias) throws Exception {
    PrivateKey key = (PrivateKey) keyStore.getKey(alias, null);
    return key;
}

Anyone has an idea what is happening and can help me to understand how to fix it? Thanks!

回答1:

As far as I know through research and trial and error, this is not currently supported.

I believe the best you can do is sign the public key of an EC key pair you generate outside of the AndroidKeyStore with an EC key pair that is stored in AndroidKeyStore. You can then send this signed public key over to the other party with your signing key certificate, generate a shared secret (outside of AndroidKeyStore), then store the SecretKey that is derived using a KDF on the generated secret. I recommend using this non-AndroidKeyStore generated key pair once (so only for the purpose of deriving the secret) and repeating this process to re-key when deemed necessary.

EDIT: When I said 'store the SecretKey', I meant in AndroidKeyStore. That key will initially be in what is called 'normal world' in this context, but its the best you can do for now.



回答2:

ECDH is supported in API level 23. Please refer android documentation on Android Keystore System

Sample code is also available in this link..