5

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!

Molka
  • 51
  • 1
  • 3

1 Answers1

3

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.

datKiDfromNY
  • 321
  • 2
  • 2
  • Note: this breaks the security model of the keystore. the key that you generate outside the store would be accessible on the phone via a jailbreak or similar attack every time you use it. – Erik Aronesty Oct 23 '18 at 20:51
  • I wouldn't say it does. The security model of the keystore is preserved - the attestation of the key in the AndroidKeyStore doesn't change. The party accepting the public key generated outside the keystore would have to deal with this risk in their authentication scheme. This is main reason I suggested ECDHE though, so forward secrecy is preserved in the case of a jailbroken device. – datKiDfromNY Nov 09 '18 at 00:13
  • Suppose your keystore-external EC private key is stolen. An attacker, can obtain that key without jail-breaking, since the key lives in app ram and apoorly coded app could leak it..... and from the next re-key event on he will be able to observe and modify all traffic (zero forward secrecy). The only thing a keystore signature does is prevent an attacker from re-keying himself. – Erik Aronesty Nov 20 '18 at 14:39
  • The external EC private key should be ephemeral to prevent that attack. The receiving party should take the necessary precautions to prevent a past key being used (certificate revocation for example) The attestation of the AndroidKeystore key remains and therefore the security model of the keystore is preserved. – datKiDfromNY Nov 25 '18 at 00:47