I know the usual way of using getting shared secrets for encryption with ECC is DH, however, this only works with two keypairs of exactly the same kind, for example two curve25519- or two p256-keypairs.
With ElGamal, one can get a symmetric key for a recipients public key no matter which kind of key they are using themselves. This works great if users don't have the same kinds of keys, and it doesn't use the same shared secret each time. This behaviour makes development and use of an application using ECC for encryption much easier and probably even is more secure (as the shared secret is different each time), so I'd prefer using ElGamal if possible.
However, it only seems to work for Short type curves - NIST, SECG, brainpool and so on. (My javascript implementation (1) is based on SJCL's implementation, but uses "elliptic" as a library, which supports Short, Montgomery and Edwards curves, while SJCL and JSBN only know Short.)
I don't really get this, as the logic behind ElGamal is really simple:
public_key = curve_param_G * secret_key
tag = curve_param_G * random_secret
key = public_key * random_secret = curve_param_G * secret_key * random_secret
key = tag*secret_key = curve_param_G * random_secret * secret_key
The implementation of multiplication for Montgomery and Edwards curves seems to be different from the multiplication function of Short curves. Still, shouldn't it work?
Is there any change to make ElGamal work with Montgomery curves like curve25519, or Edwards type curves like ed25519, and is it just implementations fault?
Or is there any reason this actually isn't possible?
Reasearching on this topic doesn't bring much detailed information(, unless you get the exact math behind Montgomery and Edwards curves, which I don't at the moment, I'm just using the elliptic library for a simple app).
Thank you for your answers :)
(1) Some pseudocode (simplified):
Get a symmetric key for a known public key (to get a symmetric key only the recipient will be able to find out knowing a public key):
ec = curveobject(curve_the_pubkey_is_on);
secret = random_secret_key();
tag = ec.g.mul(secret); // pass along with the message
key = public_key.mul(secret); // use for symmetric encryption
Get a symmetric key for a known tag (to get the symmetric key knowing the tag and own private key):
key = tag.mul(private_key); // can decrypt message with