diff --git a/Crypto/Cipher/DH.hs b/Crypto/Cipher/DH.hs
--- a/Crypto/Cipher/DH.hs
+++ b/Crypto/Cipher/DH.hs
@@ -12,13 +12,17 @@
 	, PublicNumber
 	, PrivateNumber
 	, SharedKey
+	, generateParams
+	, generatePrivate
 	, generatePublic
 	, getShared
 	) where
 
 import Number.ModArithmetic (exponantiation_rtl_binary)
-import Number.Prime
+import Number.Prime (generateSafePrime)
+import Number.Generate (generateOfSize)
 import Crypto.Random
+import Control.Arrow (first)
 
 type Params = (Integer,Integer) {- P prime, G generator -}
 
@@ -31,14 +35,22 @@
 newtype SharedKey = SharedKey Integer {- S -}
 	deriving (Show,Read,Eq,Enum,Real,Num,Ord)
 
-generateParams :: CryptoRandomGen g => g -> Params
-generateParams = undefined
+-- | generate params from a specific generator (2 or 5 are common values)
+-- we generate a safe prime (a prime number of the form 2p+1 where p is also prime)
+generateParams :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Params, g)
+generateParams rng bits generator =
+	either Left (Right . first (\p -> (p, generator))) $ generateSafePrime rng bits
 
-generatePrivate :: CryptoRandomGen g => g -> PrivateNumber
-generatePrivate rng = undefined
+-- | generate a private number with no specific property
+-- this number is usually called X in DH text.
+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 Y in DH text.
 generatePublic :: Params -> PrivateNumber -> PublicNumber
 generatePublic (p,g) (PrivateNumber x) = PublicNumber $ exponantiation_rtl_binary g x p
 
+-- | generate a shared key using our private number and the other party public number
 getShared :: Params -> PrivateNumber -> PublicNumber -> SharedKey
 getShared (p,_) (PrivateNumber x) (PublicNumber y) = SharedKey $ exponantiation_rtl_binary y x p
diff --git a/Number/Prime.hs b/Number/Prime.hs
--- a/Number/Prime.hs
+++ b/Number/Prime.hs
@@ -1,6 +1,9 @@
 module Number.Prime
 	( generatePrime
+	, generateSafePrime
 	, isProbablyPrime
+	, findPrimeFrom
+	, findPrimeFromWith
 	, primalityTestNaive
 	-- , primalityTestAKS
 	, primalityTestMillerRabin
@@ -21,18 +24,41 @@
 	| any (\p -> p `divides` n) (filter (< n) smallPrimes) = Right (False, rng)
 	| otherwise                                            = primalityTestMillerRabin rng 30 n
 
+-- | generate a prime number of the required bitsize
 generatePrime :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)
 generatePrime rng bits = case generateOfSize rng bits of
 	Left err         -> Left err
 	Right (sp, rng') -> findPrimeFrom rng' sp
 
-findPrimeFrom :: CryptoRandomGen g => g -> Integer -> Either GenError (Integer, g)
-findPrimeFrom rng n
-	| even n        = findPrimeFrom rng (n+1)
+-- | generate a prime number of the form 2p+1 where p is also prime.
+-- it is also know as a Sophie Germaine prime or safe prime.
+--
+-- The number of safe prime is significantly smaller to the number of prime,
+-- as such it shouldn't be used if this number is supposed to be kept safe.
+generateSafePrime :: CryptoRandomGen g => g -> Int -> Either GenError (Integer, g)
+generateSafePrime rng bits = case generateOfSize rng bits of
+	Left err         -> Left err
+	Right (sp, rng') -> case findPrimeFromWith rng' (\g i -> isProbablyPrime g (2*i+1)) (sp `div` 2) of
+		Left err         -> Left err
+		Right (p, rng'') -> Right (2*p+1, rng'')
+
+-- | find a prime from a starting point where the property hold.
+findPrimeFromWith :: CryptoRandomGen g => g -> (g -> Integer -> Either GenError (Bool,g)) -> Integer -> Either GenError (Integer, g)
+findPrimeFromWith rng prop n
+	| even n        = findPrimeFromWith rng prop (n+1)
 	| otherwise     = case isProbablyPrime rng n of
 		Left err               -> Left err
-		Right (isPPrime, rng') -> if isPPrime then Right (n, rng') else findPrimeFrom rng' (n+2)
+		Right (False, rng')    -> findPrimeFromWith rng' prop (n+2)
+		Right (True, rng')     ->
+			case prop rng' n of
+				Left err             -> Left err
+				Right (False, rng'') -> findPrimeFromWith rng'' prop (n+2)
+				Right (True, rng'')  -> Right (n, rng'')
 
+-- | find a prime from a starting point with no specific property.
+findPrimeFrom :: CryptoRandomGen g => g -> Integer -> Either GenError (Integer, g)
+findPrimeFrom rng n = findPrimeFromWith rng (\g _ -> Right (True, g)) n
+
 -- | Miller Rabin algorithm return if the number is probably prime or composite.
 -- the tries parameter is the number of recursion, that determines the accuracy of the test.
 primalityTestMillerRabin :: CryptoRandomGen g => g -> Int -> Integer -> Either GenError (Bool, g)
@@ -79,9 +105,9 @@
 		-- for p prime, the euler totient (# of coprime to n) is clearly n -1
 		totient = n-1
 		ubound = (fst $ sqrti totient) * (logi n)
-		logi n
-			| n == 0    = 0
-			| otherwise = 1 + logi (n `shiftR` 1)
+		logi z
+			| z == 0    = 0
+			| otherwise = 1 + logi (z `shiftR` 1)
 
 -- | Test naively is integer is prime.
 -- while naive, we skip even number and stop iteration at i > sqrt(n)
@@ -149,4 +175,5 @@
 	]
 
 {-# INLINE divides #-}
+divides :: Integer -> Integer -> Bool
 divides i n = n `mod` i == 0
diff --git a/cryptocipher.cabal b/cryptocipher.cabal
--- a/cryptocipher.cabal
+++ b/cryptocipher.cabal
@@ -1,5 +1,5 @@
 Name:                cryptocipher
-Version:             0.2.11
+Version:             0.2.12
 Description:         Symmetrical Block, Stream and PubKey Ciphers
 License:             BSD3
 License-file:        LICENSE
