# How to securely use Elgamal encryption in libgcrypt?

How secure is libgcrypt's Elgamal implementation of encryption (how different it is from textbook Elgamal), and how can I tweak padding and other preprocessing actions?

For example, I know that usign RSA I can use this S-expression to the function gcry_pk_encrypt:

(data
(flags pkcs1)
(value BLOCK))


And I can use oaep or pss instead of "pkcs1". But what do I use with Elgamal? I can encrypt and decrypt using Elgamal, using

(data
(value BLOCK))


but then I have no idea if raw Elgamal was used or if it's actually DHAES or some padded-Elgamal variant.

What is the proper way to use Elgamal in libgcrypt, and what options can I pass? Or would it be better to switch to RSA?

edit: I think that what I wanted to ask is "what is the intended use of Elgamal as implemented in libgcrypt?"

-
Unless you have a specific need for Elgamal, I'd suggest using RSA. –  mikeazo Jul 23 '12 at 1:57

I took the world's shortest look at the code, so please don't hold me to any of this. But it seems that the implementation is textbook. You provide a block of data, it gets encoded to an integer in the range 1,...,p-1 and then encrypted using standard Elgamal without padding.

There's does not seem** to be an encoding to the subgroup of quadratic residues, and this implementation is /not/ CCA secure. These probably aren't going to kill you if you're encrypting a large random key, but they're definitely not the right way to encrypt.

Rather than hacking Elgamal, I'd say you're better off encrypting with RSA-OAEP.

In the long term, libgcrypt should implement a secure KEM/DEM for Elgamal encryption. DHAES would be a great example. Alternatively the authors should give a proper (non-textbook) Elgamal implementation with a group encoding and protections against adaptive-chosen ciphertext attacks.

(Elgamal seems to be the forgotten primitive. pycrypto has the exact same problems. Nobody loves Elgamal, which is too bad because it's a great encryption scheme.)

** A footnote: I didn't look deeply into the encoding function (below), so I admit I could be wrong about this point. But I don't see anything obvious. Here's the code:

init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, gcry_pk_get_nbits (s_pkey)); rc = sexp_data_to_mpi (s_data, &data, &ctx);

-
Thank you! This was really useful. –  Jay Jul 30 '12 at 10:54