diff --git a/Data/Certificate/X509/Ext.hs b/Data/Certificate/X509/Ext.hs
new file mode 100644
--- /dev/null
+++ b/Data/Certificate/X509/Ext.hs
@@ -0,0 +1,85 @@
+-- |
+-- Module      : Data.Certificate.X509.Ext
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- extension processing module.
+--
+module Data.Certificate.X509.Ext
+	( CertificateExt
+	, Ext(..)
+	, ExtKeyUsageFlag(..)
+	, extDecode
+	) where
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ASN1.DER
+import Data.ASN1.BitArray
+import Data.Certificate.X509.Internal
+
+type CertificateExt = (OID, Bool, [ASN1])
+
+-- | key usage flag that is found in the key usage extension field.
+data ExtKeyUsageFlag =
+	  KeyUsage_digitalSignature -- (0)
+	| KeyUsage_nonRepudiation   -- (1) recent X.509 ver have renamed this bit to contentCommitment
+	| KeyUsage_keyEncipherment  -- (2)
+	| KeyUsage_dataEncipherment -- (3)
+	| KeyUsage_keyAgreement     -- (4)
+	| KeyUsage_keyCertSign      -- (5)
+	| KeyUsage_cRLSign          -- (6)
+	| KeyUsage_encipherOnly     -- (7)
+	| KeyUsage_decipherOnly     -- (8)
+	deriving (Show,Eq,Ord,Enum)
+
+-- RFC 5280
+oidSubjectKeyId, oidKeyUsage, oidBasicConstraints, oidDistributionPoints,
+                 oidPolicies, oidPoliciesMapping, oidAuthorityKeyId :: OID
+oidSubjectKeyId       = [2,5,29,14]
+oidKeyUsage           = [2,5,29,15]
+oidBasicConstraints   = [2,5,29,19]
+oidDistributionPoints = [2,5,29,31]
+oidPolicies           = [2,5,29,32]
+oidPoliciesMapping    = [2,5,29,33]
+oidAuthorityKeyId     = [2,5,29,35]
+
+-- | known X509v3 extensions
+data Ext =
+	  ExtBasicConstraints Bool
+	| ExtKeyUsage [ExtKeyUsageFlag]
+	| ExtSubjectKeyId L.ByteString
+	| ExtAuthorityKeyId B.ByteString
+	deriving (Show,Eq)
+
+-- | try decoding a certificateExt tuple into a known extension.
+extDecode :: CertificateExt -> Maybe Ext
+extDecode (oid, _, asn1)
+	| oid == oidBasicConstraints = decodeBasicConstraints asn1
+	| oid == oidSubjectKeyId     = decodeSubjectKeyId asn1
+	| oid == oidAuthorityKeyId   = decodeAuthorityKeyId asn1
+	| oid == oidKeyUsage         = decodeKeyUsage asn1
+	| otherwise                  = Nothing
+	where
+		-- basic constraints
+		decodeBasicConstraints [Start Sequence,Boolean b,End Sequence] =
+			Just (ExtBasicConstraints b)
+		decodeBasicConstraints _ = Nothing
+		-- subject key id
+		decodeSubjectKeyId [OctetString o] =
+			Just (ExtSubjectKeyId o)
+		decodeSubjectKeyId _ = Nothing
+		-- key usage
+		decodeKeyUsage [BitString bits] = Just $ ExtKeyUsage $ bitsToFlags bits
+		decodeKeyUsage _ = Nothing
+
+		decodeAuthorityKeyId [Start Sequence,Other Context 0 keyid,End Sequence] = Just $ ExtAuthorityKeyId keyid
+		decodeAuthorityKeyId _ = Nothing
+
+		bitsToFlags bits =
+			let nb = bitArrayLength bits in
+			concat $ flip map [0..(nb-1)] $ \i -> do
+				let isSet = bitArrayGetBit bits i
+				if isSet then [toEnum $ fromIntegral i] else []
diff --git a/certificate.cabal b/certificate.cabal
--- a/certificate.cabal
+++ b/certificate.cabal
@@ -1,5 +1,5 @@
 Name:                certificate
-Version:             0.9.2
+Version:             0.9.3
 Description:
     Certificates and Key reader/writer
     .
@@ -35,6 +35,7 @@
                    , time
   Exposed-modules:   Data.Certificate.X509
                      Data.Certificate.X509.Cert
+                     Data.Certificate.X509.Ext
                      Data.Certificate.PEM
                      Data.Certificate.KeyDSA
                      Data.Certificate.KeyRSA
