diff --git a/Crypto/Types/PubKey/DH.hs b/Crypto/Types/PubKey/DH.hs
--- a/Crypto/Types/PubKey/DH.hs
+++ b/Crypto/Types/PubKey/DH.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE DeriveDataTypeable #-}
 -- |
 -- Module      : Crypto.Types.PubKey.DH
 -- License     : BSD-style
@@ -7,14 +8,19 @@
 -- Portability : Excellent
 --
 module Crypto.Types.PubKey.DH
-    ( Params
+    ( Params(..)
     , PublicNumber(..)
     , PrivateNumber(..)
     , SharedKey(..)
     ) where
 
+import Data.Data
+
 -- | Represent Diffie Hellman parameters namely P (prime), and G (generator).
-type Params = (Integer,Integer)
+data Params = Params
+    { params_p :: Integer
+    , params_g :: Integer
+    } deriving (Show,Read,Eq,Data,Typeable)
 
 -- | Represent Diffie Hellman public number Y.
 newtype PublicNumber = PublicNumber Integer
diff --git a/Crypto/Types/PubKey/DSA.hs b/Crypto/Types/PubKey/DSA.hs
--- a/Crypto/Types/PubKey/DSA.hs
+++ b/Crypto/Types/PubKey/DSA.hs
@@ -7,31 +7,109 @@
 -- Portability : Excellent
 --
 module Crypto.Types.PubKey.DSA
-    ( Params
+    ( Params(..)
     , Signature
+    , PublicNumber
     , PublicKey(..)
+    , PrivateNumber
     , PrivateKey(..)
+    , KeyPair(..)
+    , toPublicKey
+    , toPrivateKey
     ) where
 
 import Data.Data
+import Data.ASN1.Types
 
+-- | DSA Public Number, usually embedded in DSA Public Key
+type PublicNumber = Integer
+
+-- | DSA Private Number, usually embedded in DSA Private Key
+type PrivateNumber = Integer
+
 -- | Represent DSA parameters namely P, G, and Q.
-type Params = (Integer,Integer,Integer)
+data Params = Params
+    { params_p :: Integer -- ^ DSA p
+    , params_g :: Integer -- ^ DSA g
+    , params_q :: Integer -- ^ DSA q
+    } deriving (Show,Read,Eq,Data,Typeable)
 
+instance ASN1Object Params where
+    toASN1 params = \xs -> Start Sequence
+                         : IntVal (params_p params)
+                         : IntVal (params_q params)
+                         : IntVal (params_g params)
+                         : End Sequence
+                         : xs
+    fromASN1 (Start Sequence:IntVal p:IntVal q:IntVal g:End Sequence:xs) =
+        Right (Params { params_p = p, params_g = g, params_q = q }, xs)
+    fromASN1 _ = Left "fromASN1: DSA.Params: unexpected format"
+
 -- | Represent a DSA signature namely R and S.
 type Signature = (Integer,Integer)
 
 -- | Represent a DSA public key.
 data PublicKey = PublicKey
-    { public_params :: Params   -- ^ DSA parameters
-    , public_y      :: Integer  -- ^ DSA public Y
+    { public_params :: Params       -- ^ DSA parameters
+    , public_y      :: PublicNumber -- ^ DSA public Y
     } deriving (Show,Read,Eq,Data,Typeable)
 
+-- DSA public key serialization doesn't typically look like this.
+-- However to provide an instance we serialize params and the public
+-- number together.
+instance ASN1Object PublicKey where
+    toASN1 pubKey = \xs -> Start Sequence
+                         : IntVal (params_p params)
+                         : IntVal (params_q params)
+                         : IntVal (params_g params)
+                         : End Sequence
+                         : IntVal (public_y pubKey)
+                         : xs
+        where params = public_params pubKey
+    fromASN1 l = case fromASN1 l of
+                    Left err -> Left err
+                    Right (dsaParams, ls) -> case ls of
+                                                IntVal dsaPub : ls2 -> Right (PublicKey dsaParams dsaPub, ls2)
+                                                _                   -> Left "fromASN1: DSA.PublicKey: unexpected format"
+
 -- | Represent a DSA private key.
 --
 -- Only x need to be secret.
 -- the DSA parameters are publicly shared with the other side.
 data PrivateKey = PrivateKey
-    { private_params :: Params   -- ^ DSA parameters
-    , private_x      :: Integer  -- ^ DSA private X
+    { private_params :: Params        -- ^ DSA parameters
+    , private_x      :: PrivateNumber -- ^ DSA private X
     } deriving (Show,Read,Eq,Data,Typeable)
+
+-- | Represent a DSA key pair
+data KeyPair = KeyPair Params PublicNumber PrivateNumber
+    deriving (Show,Read,Eq,Data,Typeable)
+
+instance ASN1Object KeyPair where
+    toASN1 (KeyPair params pub priv) = \xs ->
+          Start Sequence
+        : IntVal 0
+        : IntVal (params_p params)
+        : IntVal (params_q params)
+        : IntVal (params_g params)
+        : IntVal pub
+        : IntVal priv
+        : End Sequence
+        : xs
+    fromASN1 (Start Sequence : IntVal n : xs)
+        | n == 0    = case xs of
+                        IntVal p : IntVal q : IntVal g : IntVal pub : IntVal priv : End Sequence : xs2 ->
+                            let params = Params { params_p = p, params_g = g, params_q = q }
+                             in Right (KeyPair params pub priv, xs2)
+                        _                                                                              ->
+                            Left "fromASN1: DSA.KeyPair: invalid format (version=0)"
+        | otherwise = Left "fromASN1: DSA.KeyPair: unknown format"
+    fromASN1 _ = Left "fromASN1: DSA.KeyPair: unexpected format"
+
+-- | Public key of a DSA Key pair
+toPublicKey :: KeyPair -> PublicKey
+toPublicKey (KeyPair params pub _) = PublicKey params pub
+
+-- | Private key of a DSA Key pair
+toPrivateKey :: KeyPair -> PrivateKey
+toPrivateKey (KeyPair params _ priv) = PrivateKey params priv
diff --git a/Crypto/Types/PubKey/RSA.hs b/Crypto/Types/PubKey/RSA.hs
--- a/Crypto/Types/PubKey/RSA.hs
+++ b/Crypto/Types/PubKey/RSA.hs
@@ -9,11 +9,15 @@
 module Crypto.Types.PubKey.RSA
     ( PublicKey(..)
     , PrivateKey(..)
+    , KeyPair(..)
     , private_size
     , private_n
+    , toPublicKey
+    , toPrivateKey
     ) where
 
 import Data.Data
+import Data.ASN1.Types
 
 -- | Represent a RSA public key
 data PublicKey = PublicKey
@@ -22,6 +26,22 @@
     , public_e    :: Integer  -- ^ public exponant e
     } deriving (Show,Read,Eq,Data,Typeable)
 
+instance ASN1Object PublicKey where
+    toASN1 pubKey = \xs -> Start Sequence
+                         : IntVal (public_n pubKey)
+                         : IntVal (public_e pubKey)
+                         : End Sequence
+                         : xs
+    fromASN1 (Start Sequence:IntVal modulus:IntVal pubexp:End Sequence:xs) =
+        Right (PublicKey { public_size = calculate_modulus modulus 1
+                         , public_n    = modulus
+                         , public_e    = pubexp
+                         }
+              , xs)
+        where calculate_modulus n i = if (2 ^ (i * 8)) > n then i else calculate_modulus n (i+1)
+    fromASN1 _ =
+        Left "fromASN1: RSA.PublicKey: unexpected format"
+
 -- | Represent a RSA private key.
 -- 
 -- Only the pub, d fields are mandatory to fill.
@@ -45,3 +65,63 @@
 private_size = public_size . private_pub
 private_n    = public_n . private_pub
 private_e    = public_e . private_pub
+
+instance ASN1Object PrivateKey where
+    toASN1 privKey = \xs -> Start Sequence
+                          : IntVal 0
+                          : IntVal (public_n $ private_pub privKey)
+                          : IntVal (public_e $ private_pub privKey)
+                          : IntVal (private_d privKey)
+                          : IntVal (private_p privKey)
+                          : IntVal (private_q privKey)
+                          : IntVal (private_dP privKey)
+                          : IntVal (private_dQ privKey)
+                          : IntVal (fromIntegral $ private_qinv privKey)
+                          : End Sequence
+                          : xs
+    fromASN1 (Start Sequence
+             : IntVal 0
+             : IntVal n
+             : IntVal e
+             : IntVal d
+             : IntVal p1
+             : IntVal p2
+             : IntVal pexp1
+             : IntVal pexp2
+             : IntVal pcoef
+             : End Sequence
+             : xs) = Right (privKey, xs)
+        where calculate_modulus n i = if (2 ^ (i * 8)) > n then i else calculate_modulus n (i+1)
+              privKey = PrivateKey
+                        { private_pub  = PublicKey { public_size = calculate_modulus n 1
+                                                   , public_n    = n
+                                                   , public_e    = e
+                                                   }
+                        , private_d    = d
+                        , private_p    = p1
+                        , private_q    = p2
+                        , private_dP   = pexp1
+                        , private_dQ   = pexp2
+                        , private_qinv = pcoef
+                        }
+
+    fromASN1 _ =
+        Left "fromASN1: RSA.PrivateKey: unexpected format"
+
+-- | Represent RSA KeyPair
+--
+-- note the RSA private key contains already an instance of public key for efficiency
+newtype KeyPair = KeyPair PrivateKey
+    deriving (Show,Read,Eq,Data,Typeable)
+
+instance ASN1Object KeyPair where
+    toASN1 (KeyPair pkey) = toASN1 pkey
+    fromASN1 = fmap (\(k,s) -> (KeyPair k, s)) . fromASN1
+
+-- | Public key of a RSA KeyPair
+toPublicKey :: KeyPair -> PublicKey
+toPublicKey (KeyPair priv) = private_pub priv
+
+-- | Private key of a RSA KeyPair
+toPrivateKey :: KeyPair -> PrivateKey
+toPrivateKey (KeyPair priv) = priv
diff --git a/crypto-pubkey-types.cabal b/crypto-pubkey-types.cabal
--- a/crypto-pubkey-types.cabal
+++ b/crypto-pubkey-types.cabal
@@ -1,5 +1,5 @@
 Name:                crypto-pubkey-types
-Version:             0.2.0
+Version:             0.3.0
 Description:         Generic cryptography public keys algorithm types
 License:             BSD3
 License-file:        LICENSE
@@ -17,6 +17,7 @@
                      Crypto.Types.PubKey.DSA
                      Crypto.Types.PubKey.DH
   Build-depends:     base >= 4 && < 5
+                   , asn1-types >= 0.1 && < 0.2
 
 source-repository head
   type:     git
