diff --git a/Crypto/Cipher/ElGamal.hs b/Crypto/Cipher/ElGamal.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Cipher/ElGamal.hs
@@ -0,0 +1,70 @@
+-- |
+-- Module      : Crypto.Cipher.ElGamal
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : Good
+--
+-- This module is a work in progress. do not use:
+-- it might eat your dog, your data or even both.
+--
+-- TODO: provide a mapping between integer and ciphertext
+--       generate numbers correctly
+--
+module Crypto.Cipher.ElGamal
+	( Params
+	, PublicNumber
+	, PrivateNumber
+	, SharedKey
+    , generatePrivate
+    , generatePublic
+    , encryptWith
+    , encrypt
+    , decrypt
+    , sign
+    , verify
+    ) where
+
+import Number.ModArithmetic (exponantiation, inverse)
+import Number.Prime (generateSafePrime)
+import Number.Generate (generateOfSize, generateBetween)
+import Crypto.Types.PubKey.DH
+import Crypto.Random
+import Control.Arrow (first)
+import Control.Applicative ((<$>))
+import Data.Maybe (fromJust)
+
+-- | generate a private number with no specific property
+-- this number is usually called a.
+-- 
+-- FIXME replace generateOfSize by generateBetween [0, q-1]
+generatePrivate :: CryptoRandomGen g => g -> Int -> Either GenError (PrivateNumber, g)
+generatePrivate rng bits = either Left (Right . first PrivateNumber) $ generateOfSize rng bits
+
+-- | generate a public number that is for the other party benefits.
+-- this number is usually called h=g^a
+generatePublic :: Params -> PrivateNumber -> PublicNumber
+generatePublic (p,g) (PrivateNumber a) = PublicNumber $ exponantiation g a p
+
+-- | encrypt with a specified ephemeral key
+-- do not reuse ephemeral key.
+encryptWith :: PrivateNumber -> Params -> PublicNumber -> Integer -> (Integer,Integer)
+encryptWith (PrivateNumber b) (p,g) (PublicNumber h) m = (c1,c2)
+    where s  = exponantiation h b p
+          c1 = exponantiation g b p
+          c2 = (s * m) `mod` p
+
+-- | encrypt a message using params and public keys
+-- will generate b (called the ephemeral key)
+encrypt :: CryptoRandomGen g => g -> Params -> PublicNumber -> Integer -> Either GenError ((Integer,Integer), g)
+encrypt rng params public m = (\(b,rng') -> (encryptWith b params public m,rng')) <$> generatePrivate rng 1024
+
+-- | decrypt message
+decrypt :: Params -> PrivateNumber -> (Integer, Integer) -> Integer
+decrypt (p,g) (PrivateNumber a) (c1,c2) = (c2 * sm1) `mod` p
+    where s   = exponantiation c1 a p
+          sm1 = fromJust $ inverse s p -- always inversible in Zp
+
+sign = undefined
+
+verify = undefined
diff --git a/cbits/aes/aes.h b/cbits/aes/aes.h
new file mode 100644
--- /dev/null
+++ b/cbits/aes/aes.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010-2012 Vincent Hanquez <vincent@snarc.org>
+ * 
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of his contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef CRYPTOCIPHER_AES_H
+#define CRYPTOCIPHER_AES_H
+
+#define AES128_NB_ROUNDS 10
+
+#include <stdint.h>
+
+/* aes_key128 need to be 16 aligned by higher layer using the code. */
+typedef struct { uint8_t _data[20]; } aes_key128;
+
+void aes_generate_key128(aes_key128 *key, uint8_t *ikey);
+
+/* ECB mode */
+void aes_encrypt(uint8_t *out, aes_key128 *key, uint8_t *in, uint32_t blocks);
+void aes_decrypt(uint8_t *out, aes_key128 *key, uint8_t *in, uint32_t blocks);
+
+/* CBC mode */
+void aes_encrypt_cbc(uint8_t *out, aes_key128 *key, uint8_t *iv, uint8_t *in, uint32_t blocks);
+void aes_decrypt_cbc(uint8_t *out, aes_key128 *key, uint8_t *iv, uint8_t *in, uint32_t blocks);
+
+#endif
diff --git a/cryptocipher.cabal b/cryptocipher.cabal
--- a/cryptocipher.cabal
+++ b/cryptocipher.cabal
@@ -1,5 +1,5 @@
 Name:                cryptocipher
-Version:             0.3.1
+Version:             0.3.2
 Description:         Symmetrical Block, Stream and PubKey Ciphers
 License:             BSD3
 License-file:        LICENSE
@@ -12,6 +12,7 @@
 Homepage:            http://github.com/vincenthz/hs-cryptocipher
 Cabal-Version:       >=1.8
 Extra-Source-Files:  Tests/*.hs
+                     cbits/aes/aes.h
 
 Flag benchmark
   Description:       Build benchmarks
@@ -29,7 +30,7 @@
                    , ghc-prim
                    , primitive
                    , crypto-api >= 0.5
-                   , crypto-pubkey-types
+                   , crypto-pubkey-types >= 0.1 && < 0.2
                    , tagged
                    , cereal
   Exposed-modules:   Crypto.Cipher.RC4
@@ -45,6 +46,7 @@
                      Number.Basic
                      Number.Polynomial
                      Number.Prime
+                     Crypto.Cipher.ElGamal
   ghc-options:       -Wall
   if flag(aesni)
     cpp-options:     -DHAVE_AESNI
