I've written the below code following the official guide for ECDH Key Agreement on Android.
private static final String EC_SPEC = "p-256";
private static final String KEY_PAIR_NAME = "abcdefgh";
private static final String MAC_ALG = "HMACSHA256";
private static final String INFO_TAG = "ECDH p-256 AES-256-GCM-SIV\0";
private static final String KEY_AGREEMENT_ALG = "ECDH";
private static final String KEY_STORE_PROVIDER = "AndroidKeyStore";
public static KeyPair generateKeys() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, ParseException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_EC, KEY_STORE_PROVIDER);
keyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(
KEY_PAIR_NAME,
KeyProperties.PURPOSE_AGREE_KEY)
.setAlgorithmParameterSpec(new ECGenParameterSpec(EC_SPEC))
.setUserAuthenticationRequired(false)
.setKeyValidityEnd(DateFormat.getDateInstance().parse("Aug 1, 2199"))
.build());
return keyPairGenerator.generateKeyPair();
}
public static byte[] sharedSecret(PrivateKey mine, PublicKey remote) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException {
KeyAgreement keyAgreement = KeyAgreement.getInstance(KEY_AGREEMENT_ALG, KEY_STORE_PROVIDER);
//Line 55 here ↓ where error occurs
keyAgreement.init(mine);
keyAgreement.doPhase(remote, true);
return keyAgreement.generateSecret();
}
But at the time of execution the code throws below error :
W/System.err: android.security.keystore.KeyPermanentlyInvalidatedException: Key permanently invalidated
W/System.err: at android.security.keystore2.KeyStoreCryptoOperationUtils.getInvalidKeyException(KeyStoreCryptoOperationUtils.java:123)
W/System.err: at android.security.keystore2.AndroidKeyStoreKeyAgreementSpi.ensureKeystoreOperationInitialized(AndroidKeyStoreKeyAgreementSpi.java:228)
W/System.err: at android.security.keystore2.AndroidKeyStoreKeyAgreementSpi.engineInit(AndroidKeyStoreKeyAgreementSpi.java:96)
W/System.err: at javax.crypto.KeyAgreement.init(KeyAgreement.java:498)
W/System.err: at javax.crypto.KeyAgreement.init(KeyAgreement.java:470)
W/System.err: at app.exploitr.sec.rts.security.ECCUtil.sharedSecret(ECCUtil.java:55)
I've tried to test the code in the following manner,
try {
KeyPair one = ECCUtil.generateKeys();
KeyPair two = ECCUtil.generateKeys();
byte[] sec_one = ECCUtil.sharedSecret(one.getPrivate(), two.getPublic());
byte[] sec_two = ECCUtil.sharedSecret(two.getPrivate(), one.getPublic());
Log.d("TAG 1st SHARED", new String(sec_one));
Log.d("TAG 2nd SHARED", new String(sec_two));
} catch (IOException | GeneralSecurityException | ParseException e) {
e.printStackTrace();
}
I can't understand why the keys are getting permanently invalidated instantly despite of setting user authentication disabled or large timeout. As key generation has issues with emulators and I've only 1 Android 12 device (KeyProperties.PURPOSE_AGREE_KEY was introduced in API 31) I tried to generate and test both the local and remote keys on the device. What should be done here?