diff --git a/Certificate.hs b/Certificate.hs
--- a/Certificate.hs
+++ b/Certificate.hs
@@ -5,7 +5,7 @@
 import qualified Data.ByteString as B
 import qualified Data.Text.Lazy as T
 import Data.Text.Lazy.Encoding (decodeUtf8)
-import Data.Certificate.X509
+import qualified Data.Certificate.X509 as X509
 import Data.Certificate.KeyRSA as KeyRSA
 import Data.Certificate.KeyDSA as KeyDSA
 import Data.Certificate.PEM
@@ -14,7 +14,15 @@
 import Control.Applicative ((<$>))
 import Data.Maybe
 import System.Exit
+import System.Certificate.X509 as SysCert
 
+-- for signing/verifying certificate
+import qualified Crypto.Hash.SHA1 as SHA1
+import qualified Crypto.Hash.MD2 as MD2
+import qualified Crypto.Hash.MD5 as MD5
+import qualified Crypto.Cipher.RSA as RSA
+import qualified Crypto.Cipher.DSA as DSA
+
 import Data.ASN1.DER (decodeASN1Stream, ASN1(..), ASN1ConstructionType(..))
 import Numeric
 
@@ -28,19 +36,19 @@
 
 showExts e = putStrLn $ show e
 
-showCert :: X509 -> IO ()
-showCert (X509 cert _ sigalg sigbits) = do
-	putStrLn ("version: " ++ show (certVersion cert))
-	putStrLn ("serial:  " ++ show (certSerial cert))
-	putStrLn ("sigalg:  " ++ show (certSignatureAlg cert))
+showCert :: X509.X509 -> IO ()
+showCert (X509.X509 cert _ sigalg sigbits) = do
+	putStrLn ("version: " ++ show (X509.certVersion cert))
+	putStrLn ("serial:  " ++ show (X509.certSerial cert))
+	putStrLn ("sigalg:  " ++ show (X509.certSignatureAlg cert))
 	putStrLn "issuer:"
-	showDN $ certIssuerDN cert
+	showDN $ X509.certIssuerDN cert
 	putStrLn "subject:"
-	showDN $ certSubjectDN cert
-	putStrLn ("valid:  " ++ show (certValidity cert))
-	putStrLn ("pk:     " ++ show (certPubKey cert))
+	showDN $ X509.certSubjectDN cert
+	putStrLn ("valid:  " ++ show (X509.certValidity cert))
+	putStrLn ("pk:     " ++ show (X509.certPubKey cert))
 	putStrLn "exts:"
-	showExts $ certExtensions cert
+	showExts $ X509.certExtensions cert
 	putStrLn ("sigAlg: " ++ show sigalg)
 	putStrLn ("sig:    " ++ show sigbits)
 
@@ -109,17 +117,63 @@
 	p (Other tc tn x)        = putStr "other"
 
 doMain :: CertMainOpts -> IO ()
-doMain opts@(X509Opt _ _ _ _) = do
+doMain opts@(X509 _ _ _ _ _) = do
 	cert <- maybe (error "cannot read PEM certificate") (id) . parsePEMCert <$> B.readFile (head $ files opts)
 
 	when (raw opts) $ putStrLn $ hexdump $ L.fromChunks [cert]
 	when (asn1 opts) $ case decodeASN1Stream $ L.fromChunks [cert] of
 		Left err   -> error ("decoding ASN1 failed: " ++ show err)
 		Right asn1 -> showASN1 asn1
-	when (text opts || not (or [asn1 opts,raw opts])) $ case decodeCertificate $ L.fromChunks [cert] of
+
+	let x509o = X509.decodeCertificate $ L.fromChunks [cert]
+	let x509  = case x509o of
 		Left err   -> error ("decoding certificate failed: " ++ show err)
-		Right c    -> showCert c
+		Right c    -> c
+	when (text opts || not (or [asn1 opts,raw opts])) $ showCert x509
+	when (verify opts) $ verifyCert x509
 	exitSuccess
+	where
+		verifyCert x509@(X509.X509 cert _ sigalg sig) = do
+			sysx509 <- SysCert.findCertificate (matchsysX509 cert)
+			case sysx509 of
+				Nothing                        -> putStrLn "couldn't find signing certificate"
+				Just (X509.X509 syscert _ _ _) -> do
+					verifyAlg (B.concat $ L.toChunks $ X509.getSigningData x509)
+					          (B.pack sig)
+					          sigalg
+					          (X509.certPubKey syscert)
+
+		rsaVerify h hdesc pk a b = either (Left . show) (Right) $ RSA.verify h hdesc pk a b
+
+		verifyF X509.SignatureALG_md2WithRSAEncryption (X509.PubKeyRSA rsakey) =
+			rsaVerify MD2.hash (B.pack [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]) (mkRSA rsakey)
+
+		verifyF X509.SignatureALG_md5WithRSAEncryption (X509.PubKeyRSA rsakey) =
+			rsaVerify MD5.hash (B.pack [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]) (mkRSA rsakey)
+
+		verifyF X509.SignatureALG_sha1WithRSAEncryption (X509.PubKeyRSA rsakey) =
+			rsaVerify SHA1.hash (B.pack [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10]) (mkRSA rsakey)
+
+		verifyF X509.SignatureALG_dsaWithSHA1 (X509.PubKeyDSA (pub,p,q,g)) =
+			(\_ _ -> Left "unimplemented DSA checking")
+
+		verifyF _ _ =
+			(\_ _ -> Left "unexpected/wrong signature")
+
+		mkRSA (lenmodulus, modulus, e) =
+			RSA.PublicKey { RSA.public_sz = lenmodulus, RSA.public_n = modulus, RSA.public_e = e }
+
+		verifyAlg toSign expectedSig sigalg pk =
+			let f = verifyF sigalg pk in
+			case f toSign expectedSig of
+				Left err    -> putStrLn ("certificate couldn't be verified: something happened: " ++ show err)
+				Right True  -> putStrLn "certificate verified"
+				Right False -> putStrLn "certificate not verified"
+
+		matchsysX509 cert (X509.X509 syscert _ _ _) = do
+			let x = X509.certSubjectDN syscert
+			let y = X509.certIssuerDN cert
+			x == y
 	
 doMain (Key files) = do
 	content <- B.readFile $ head files
@@ -141,22 +195,24 @@
 			putStrLn "no recognized private key found"
 
 data CertMainOpts =
-	  X509Opt
-		{ files :: [FilePath]
-		, asn1  :: Bool
-		, text  :: Bool
-		, raw   :: Bool
+	  X509
+		{ files  :: [FilePath]
+		, asn1   :: Bool
+		, text   :: Bool
+		, raw    :: Bool
+		, verify :: Bool
 		}
 	| Key
 		{ files :: [FilePath]
 		}
 	deriving (Show,Data,Typeable)
 
-x509Opts = X509Opt
-	{ files = def &= args &= typFile
-	, asn1  = def
-	, text  = def
-	, raw   = def
+x509Opts = X509
+	{ files  = def &= args &= typFile
+	, asn1   = def
+	, text   = def
+	, raw    = def
+	, verify = def
 	} &= help "x509 certificate related commands"
 
 keyOpts = Key
diff --git a/Data/Certificate/X509.hs b/Data/Certificate/X509.hs
--- a/Data/Certificate/X509.hs
+++ b/Data/Certificate/X509.hs
@@ -15,13 +15,15 @@
 	-- * Data Structure (reexported from X509Cert)
 	, SignatureALG(..)
 	, PubKeyALG(..)
-	, PubKeyDesc(..)
 	, PubKey(..)
 	, ASN1StringType(..)
 	, ASN1String
 	, Certificate(..)
 	, CertificateExts(..)
 
+	-- * helper for signing/veryfing certificate
+	, getSigningData
+
 	-- * serialization from ASN1 bytestring
 	, decodeCertificate
 	, encodeCertificate
@@ -38,6 +40,15 @@
 
 data X509 = X509 Certificate (Maybe L.ByteString) SignatureALG [Word8]
 	deriving (Show,Eq)
+
+{- | get signing data related to a X509 message,
+ - which is either the cached data or the encoded certificate -}
+getSigningData :: X509 -> L.ByteString
+getSigningData (X509 _ (Just e) _ _)   = e
+getSigningData (X509 cert Nothing _ _) = e
+	where
+		(Right e) = encodeASN1Stream header
+		header    = asn1Container Sequence $ encodeCertificateHeader cert
 
 {- | decode an X509 from a bytestring
  - the structure is the following:
diff --git a/Data/Certificate/X509Cert.hs b/Data/Certificate/X509Cert.hs
--- a/Data/Certificate/X509Cert.hs
+++ b/Data/Certificate/X509Cert.hs
@@ -3,7 +3,6 @@
 	-- * Data Structure
 	  SignatureALG(..)
 	, PubKeyALG(..)
-	, PubKeyDesc(..)
 	, PubKey(..)
 	, ASN1StringType(..)
 	, ASN1String
@@ -51,17 +50,17 @@
 	  PubKeyALG_RSA
 	| PubKeyALG_DSA
 	| PubKeyALG_ECDSA
+	| PubKeyALG_DH
 	| PubKeyALG_Unknown OID
 	deriving (Show,Eq)
 
-data PubKeyDesc =
-	  PubKeyRSA (Int, Integer, Integer)              -- ^ RSA format with (len modulus, modulus, e)
-	| PubKeyDSA (Integer, Integer, Integer, Integer) -- ^ DSA format with (pub, p, q, g)
+data PubKey =
+	  PubKeyRSA (Int,Integer,Integer)                -- ^ RSA format with (len modulus, modulus, e)
+	| PubKeyDSA (Integer,Integer,Integer,Integer)    -- ^ DSA format with (pub, p, q, g)
+	| PubKeyDH (Integer,Integer,Integer,Maybe Integer,([Word8], Integer))
+	                                                 -- ^ DH format with (p,g,q,j,(seed,pgenCounter))
 	| PubKeyECDSA [ASN1]                             -- ^ ECDSA format not done yet FIXME
-	| PubKeyUnknown [Word8]                          -- ^ unrecognized format
-	deriving (Show,Eq)
-
-data PubKey = PubKey PubKeyALG PubKeyDesc -- OID RSA|DSA|rawdata
+	| PubKeyUnknown OID [Word8]                      -- ^ unrecognized format
 	deriving (Show,Eq)
 
 -- FIXME use a proper standard type for representing time.
@@ -79,7 +78,7 @@
 	| CertKeyUsageDecipherOnly
 	deriving (Show, Eq)
 
-data ASN1StringType = UTF8 | Printable | Univ | BMP | IA5 deriving (Show,Eq)
+data ASN1StringType = UTF8 | Printable | Univ | BMP | IA5 | T61 deriving (Show,Eq)
 type ASN1String = (ASN1StringType, Text)
 
 data Certificate = Certificate
@@ -109,21 +108,22 @@
 
 {- | parse a RSA pubkeys from ASN1 encoded bits.
  - return PubKeyRSA (len-modulus, modulus, e) if successful -}
-parse_RSA :: ByteString -> PubKeyDesc
+parse_RSA :: ByteString -> ParseASN1 PubKey
 parse_RSA bits =
 	case decodeASN1Stream $ bits of
 		Right [Start Sequence, IntVal modulus, IntVal pubexp, End Sequence] ->
-			PubKeyRSA (calculate_modulus modulus 1, modulus, pubexp)
+			return $ PubKeyRSA (calculate_modulus modulus 1, modulus, pubexp)
 		_ ->
-			PubKeyUnknown $ L.unpack bits
+			throwError ("bad RSA format")
 	where
 		calculate_modulus n i = if (2 ^ (i * 8)) > n then i else calculate_modulus n (i+1)
 
-parse_ECDSA :: ByteString -> PubKeyDesc
+parse_ECDSA :: ByteString -> ParseASN1 PubKey
 parse_ECDSA bits =
 	case decodeASN1Stream bits of
-		Right l -> PubKeyECDSA l
-		Left x  -> PubKeyUnknown $ map (fromIntegral . fromEnum) $ show x
+		Right l -> return $ PubKeyECDSA l
+		Left _  -> return $ PubKeyUnknown (pubkeyalgOID PubKeyALG_ECDSA) (L.unpack bits)
+
 parseCertHeaderVersion :: ParseASN1 Int
 parseCertHeaderVersion = do
 	v <- onNextContainerMaybe (Container Context 0) $ do
@@ -154,6 +154,7 @@
 	[ ([1,2,840,113549,1,1,1], PubKeyALG_RSA)
 	, ([1,2,840,10040,4,1],    PubKeyALG_DSA)
 	, ([1,2,840,10045,2,1],    PubKeyALG_ECDSA)
+	, ([1,2,840,10046,2,1],    PubKeyALG_DH)
 	]
 
 oidSig :: OID -> SignatureALG
@@ -170,6 +171,13 @@
 pubkeyalgOID (PubKeyALG_Unknown oid) = oid
 pubkeyalgOID sig = maybe [] fst $ find ((==) sig . snd) pk_table
 
+pubkeyToAlg :: PubKey -> PubKeyALG
+pubkeyToAlg (PubKeyRSA _)         = PubKeyALG_RSA
+pubkeyToAlg (PubKeyDSA _)         = PubKeyALG_DSA
+pubkeyToAlg (PubKeyDH _)          = PubKeyALG_DH
+pubkeyToAlg (PubKeyECDSA _)       = PubKeyALG_ECDSA
+pubkeyToAlg (PubKeyUnknown oid _) = PubKeyALG_Unknown oid
+
 parseCertHeaderAlgorithmID :: ParseASN1 SignatureALG
 parseCertHeaderAlgorithmID = do
 	n <- getNextContainer Sequence
@@ -184,6 +192,7 @@
 asn1String (UniversalString x) = (Univ, x)
 asn1String (BMPString x)       = (BMP, x)
 asn1String (IA5String x)       = (IA5, x)
+asn1String (T61String x)       = (IA5, x)
 asn1String x                   = error ("not a print string " ++ show x)
 
 encodeAsn1String :: ASN1String -> ASN1
@@ -192,6 +201,7 @@
 encodeAsn1String (Univ, x)      = UniversalString x
 encodeAsn1String (BMP, x)       = BMPString x
 encodeAsn1String (IA5, x)       = IA5String x
+encodeAsn1String (T61, x)       = T61String x
 
 parseCertHeaderDN :: ParseASN1 [ (OID, ASN1String) ]
 parseCertHeaderDN = do
@@ -222,23 +232,21 @@
 	l <- getNextContainer Sequence
 	bits <- getNextBitString
 	case l of
-		[OID pkalg,Null]                                                   -> do
+		[OID pkalg,Null] -> do
 			let sig = oidPubKey pkalg
-			let desc = case sig of
+			case sig of
 				PubKeyALG_RSA -> parse_RSA bits
-				_             -> PubKeyUnknown $ L.unpack bits
-			return $ PubKey sig desc
-		[OID pkalg,OID pkalg2]                                            -> do
+				_             -> return $ PubKeyUnknown pkalg $ L.unpack bits
+		[OID pkalg,OID _] -> do
 			let sig = oidPubKey pkalg
-			let desc = case sig of
+			case sig of
 				PubKeyALG_ECDSA  -> parse_ECDSA bits
-				_                -> PubKeyUnknown $ L.unpack bits
-			return $ PubKey sig desc
+				_                -> return $ PubKeyUnknown pkalg $ L.unpack bits
 		[OID pkalg,Start Sequence,IntVal p,IntVal q,IntVal g,End Sequence] -> do
 			let sig = oidPubKey pkalg
 			case decodeASN1Stream bits of
-				Right [IntVal dsapub] -> return $ PubKey sig (PubKeyDSA (dsapub, p, q, g))
-				_                     -> throwError "unrecognized DSA pub format"
+				Right [IntVal dsapub] -> return $ PubKeyDSA (dsapub, p, q, g)
+				_                     -> return $ PubKeyUnknown pkalg $ L.unpack bits
 		n ->
 			throwError ("subject public key bad format : " ++ show n)
 
@@ -347,19 +355,23 @@
 		dnSet (oid, stringy) = asn1Container Set (asn1Container Sequence [OID oid, encodeAsn1String stringy])
 
 encodePK :: PubKey -> [ASN1]
-encodePK (PubKey sig (PubKeyRSA (_, modulus, e))) =
-	asn1Container Sequence (asn1Container Sequence [ OID $ pubkeyalgOID sig, Null ] ++ [BitString 0 bits])
+encodePK k@(PubKeyRSA (_, modulus, e)) =
+	asn1Container Sequence (asn1Container Sequence [pkalg,Null] ++ [BitString 0 bits])
 	where
+		pkalg        = OID $ pubkeyalgOID $ pubkeyToAlg k
 		(Right bits) = encodeASN1Stream $ asn1Container Sequence [IntVal modulus, IntVal e]
 
-encodePK (PubKey sig (PubKeyDSA (pub, p, q, g)))  =
-	asn1Container Sequence (asn1Container Sequence ([OID $ pubkeyalgOID sig] ++ dsaseq) ++ [BitString 0 bits])
+encodePK k@(PubKeyDSA (pub, p, q, g)) =
+	asn1Container Sequence (asn1Container Sequence ([pkalg] ++ dsaseq) ++ [BitString 0 bits])
 	where
+		pkalg        = OID $ pubkeyalgOID $ pubkeyToAlg k
 		dsaseq       = asn1Container Sequence [IntVal p,IntVal q,IntVal g]
 		(Right bits) = encodeASN1Stream [IntVal pub]
 
-encodePK (PubKey sig (PubKeyUnknown l))           = 
-	asn1Container Sequence (asn1Container Sequence [OID $ pubkeyalgOID sig, Null] ++ [BitString 0 $ L.pack l])
+encodePK k@(PubKeyUnknown _ l) =
+	asn1Container Sequence (asn1Container Sequence [pkalg,Null] ++ [BitString 0 $ L.pack l])
+	where
+		pkalg = OID $ pubkeyalgOID $ pubkeyToAlg k
 
 encodeCertificateHeader :: Certificate -> [ASN1]
 encodeCertificateHeader cert =
diff --git a/System/Certificate/X509.hs b/System/Certificate/X509.hs
new file mode 100644
--- /dev/null
+++ b/System/Certificate/X509.hs
@@ -0,0 +1,81 @@
+-- |
+-- Module      : System.Certificate.X509
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : linux only
+--
+-- this module is portable to unix system where there is usually
+-- a /etc/ssl/certs with system X509 certificates.
+--
+-- the path can be dynamically override using the environment variable
+-- defined by envPathOverride in the module, which by
+-- default is SYSTEM_CERTIFICATE_PATH
+--
+module System.Certificate.X509
+	( getSystemPath
+	, readAll
+	, findCertificate
+	) where
+
+import System.Directory (getDirectoryContents)
+import System.Environment (getEnv)
+import Data.List (isPrefixOf)
+
+import Data.Either
+import Data.Certificate.X509
+import Data.Certificate.PEM
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+
+import Control.Applicative ((<$>))
+import Control.Exception
+import Control.Monad
+
+import Prelude hiding (catch)
+
+defaultSystemPath :: FilePath
+defaultSystemPath = "/etc/ssl/certs/"
+
+envPathOverride :: String
+envPathOverride = "SYSTEM_CERTIFICATE_PATH"
+
+getSystemPath :: IO FilePath
+getSystemPath = catch (getEnv envPathOverride) inDefault
+	where
+		inDefault :: IOException -> IO FilePath
+		inDefault _ = return defaultSystemPath
+
+data ReadErr =
+	  Exception IOException
+	| CertError String
+	deriving (Show,Eq)
+
+readCertificate :: FilePath -> IO (Either ReadErr X509)
+readCertificate file = do
+	rawdata <- try $ B.readFile file :: IO (Either IOException B.ByteString)
+	either (return . Left . Exception) parseCert $ rawdata
+	where
+		parseCert pemdata = case parsePEMCert pemdata of
+			Nothing       -> return $ Left $ CertError "certificate not in PEM format"
+			Just certdata -> do
+				return $ either (Left . CertError) Right $ decodeCertificate $ L.fromChunks [certdata]
+
+readAll :: IO [Either ReadErr X509]
+readAll = do
+	path      <- getSystemPath
+	certfiles <- filter (not . isPrefixOf ".") <$> getDirectoryContents path
+	forM certfiles $ \certfile -> readCertificate (path ++ certfile)
+
+findCertificate :: (X509 -> Bool) -> IO (Maybe X509)
+findCertificate f = do
+	path      <- getSystemPath
+	certfiles <- filter (not . isPrefixOf ".") <$> getDirectoryContents path
+	loop $ map (path ++) certfiles
+	where
+		loop []     = return Nothing
+		loop (x:xs) = do
+			ox509 <- readCertificate x
+			case ox509 of
+				Left _     -> loop xs
+				Right x509 -> if f x509 then return $ Just x509 else loop xs
diff --git a/certificate.cabal b/certificate.cabal
--- a/certificate.cabal
+++ b/certificate.cabal
@@ -1,5 +1,5 @@
 Name:                certificate
-Version:             0.6.0
+Version:             0.7.0
 Description:
     Certificates and Key reader/writer
     .
@@ -26,17 +26,19 @@
   Default:           False
 
 Library
-  Build-Depends:     base >= 3 && < 7,
-                     bytestring,
-                     text >= 0.11,
-                     mtl,
-                     asn1-data >= 0.4.5 && < 0.5,
-                     base64-bytestring
+  Build-Depends:     base >= 3 && < 5
+                   , bytestring
+                   , text >= 0.11
+                   , mtl
+                   , asn1-data >= 0.4.6 && < 0.5
+                   , base64-bytestring
+                   , directory
   Exposed-modules:   Data.Certificate.X509,
                      Data.Certificate.X509Cert,
                      Data.Certificate.PEM,
                      Data.Certificate.KeyDSA
                      Data.Certificate.KeyRSA
+                     System.Certificate.X509
   Other-modules:     Data.Certificate.X509Internal
   ghc-options:       -Wall
 
@@ -44,7 +46,11 @@
   Main-Is:           Certificate.hs
   if flag(executable)
     Buildable:       True
-    Build-depends:   cmdargs, text >= 0.11
+    Build-depends:   cmdargs
+                   , text >= 0.11
+                   , cryptohash
+                   , cryptocipher >= 0.2.4
+                   , directory
   else
     Buildable:       False
 
