Search code examples
javaandroidelliptic-curvediffie-hellmanspongycastle

Can KeyAgreement be used without AlgorithmParameterSpec?


In my Android application working with SpongyCastle, I want to perform ECDH Key Exchange using a specific elliptic curve (prime192v1) and I am using this code to generate byte[] representation of private and public params:

        try{
            KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", "SC");

            org.spongycastle.jce.spec.ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime192v1");
            g.initialize(ecSpec, new SecureRandom());

            KeyPair kp1 = g.generateKeyPair();
            KeyPair kp2 = g.generateKeyPair();

            // Alice generated this
            byte[] privK1 = kp1.getPrivate().getEncoded();
            byte[] pubK1= kp1.getPrivate().getEncoded();

            // Bob generated this
            byte[] privK2 = kp2.getPrivate().getEncoded();
            byte[] pubK2= kp2.getPrivate().getEncoded();

        }catch(Exception e)
        {
            Log.e(LOGTAG, "Exception caught in ECDHInit function");
        }

now lets assume Alice and Bob save their private keys locally, exchange pubK1 and pubK2 and want to proceed with setting a shared secret (they have both keys now in byte[] format). I will describe only case of Alice, as for Bob this is identical:

KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "SC");

PrivateKey privateKey = KeyFactory.getInstance("ECDH", "SC").generatePrivate(new PKCS8EncodedKeySpec(privK1));
PublicKey publicKey = KeyFactory.getInstance("ECDH", "SC").generatePublic(new X509EncodedKeySpec(pubK2));

Here comes my question - using the following code, I manage to get same shared secret for both Alice and Bob

keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);

byte[] sharedSecret = SHA256(keyAgreement.generateSecret());

but I specify nowhere my special curve prime192v1

If I try to supply this in this way:

org.spongycastle.jce.spec.ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("prime192v1");

keyAgreement.init(privateKey, ecSpec);
keyAgreement.doPhase(publicKey, true);

byte[] sharedSecret = SHA256(keyAgreement.generateSecret());

an Exception is thrown saying

java.security.InvalidAlgorithmParameterException: No algorithm parameters supported

Why can't I supply my desired parameter? Does the KeyAgreement somehow deduce this from the private key?

Thanks!


Solution

  • So it turns out I had the answer right there in front of me in the Android Studio debugger. Upon inspecting PrivateKey object I found internal member privateKey.ecSpec which contains all the details of selected curve. So passing arguments is unnecessary and throws an error, use the code without providing additional ecSpec