I am trying to used SpongyCastle on Android for ECDH secp384r1 Public/Private Key pair generation. The problem I an running into is, the keys that I am generating are way too big.
The public key is 120 bytes and the private key is 194 bytes. There is obviously some sort of encoding going on here. I do not want all of this extra info, I am looking for the 49 byte and 48 byte compressed public/private keys.
Here is how I am generating my keys:
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("secp384r1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH", "SC");
kpg.initialize(ecParamSpec);
KeyPair kpA = kpg.generateKeyPair();
byte[] publicKeyBytes = kpA.getPublic().getEncoded();
byte[] privateKeyBytes = kpA.getPrivate().getEncoded();
I am going down this route because I was previously using CryptoPP and the NDK to generate the key pairs and extract the shared secret, which you can see an example of here.
However I ran into an issue getting CryptoPP to work on Android Marshmallow, so now I am resorting to SpongyCastle.
The main issue being, this needs to work with an iOS app this is already using the CryptoPP implementation, so I need to figure out how to make this line up with that version, if that is even possible.
Basically I need a Java SpongyCastle implementation that lines up with the following C++ cryptopp implementation:
// Generate a public private key pair using ECDH (Elliptic Curve Diffie Hellman)
OID CURVE = secp384r1(); // the key is 384 bits (48 bytes) long
AutoSeededRandomPool rng;
// Because we are using point compression
// Private Key 48 bytes
// Public Key 49 bytes
// If compression was not used the public key would be 65 bytes long
ECDH < ECP >::Domain dhA( CURVE );
dhA.AccessGroupParameters().SetPointCompression(true);
SecByteBlock privA(dhA.PrivateKeyLength()), pubA(dhA.PublicKeyLength());
dhA.GenerateKeyPair(rng, privA, pubA);
jobject publicKeyByteBuffer = (*env).NewDirectByteBuffer(pubA.BytePtr(), pubA.SizeInBytes());
jobject privateKeyByteBuffer = (*env).NewDirectByteBuffer(privA.BytePtr(), privA.SizeInBytes());
// Return the ECDH Key Pair back as a Java ECDHKeyPair object
jclass keyPairClass = (*env).FindClass("com/tcolligan/ecdhtest/ECDHKeyPair");
jmethodID midConstructor = (*env).GetMethodID(keyPairClass, "<init>", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)V");
jobject keyPairObject = (*env).NewObject(keyPairClass, midConstructor, publicKeyByteBuffer, privateKeyByteBuffer);
return keyPairObject;
The first step is I need to figure out how to extract the 49 and 48 byte compressed keys from the SpongyCastle implementation.
After that extracting the shared secret using those keys would be the priority. I am pretty new to Encryption overall and using these libraries, so any help here would be greatly appreciated.
I was able to figure out the answer. The following code will give me keys with the sizes that I am looking for.
ECGenParameterSpec ecParamSpec = new ECGenParameterSpec("secp384r1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH", "SC");
kpg.initialize(ecParamSpec);
KeyPair kpA = kpg.generateKeyPair();
BCECPublicKey publicKey = (BCECPublicKey)kpA.getPublic();
BCECPrivateKey privateKey = (BCECPrivateKey)kpA.getPrivate();
byte[] publicKeyBytes = publicKey.getQ().getEncoded(true);
byte[] privateKeyBytes = privateKey.getD().toByteArray();
Good news is, it also seems to be compatible with the cryptopp C++ implementation.