diff --git a/Data/X509/Ext.hs b/Data/X509/Ext.hs
--- a/Data/X509/Ext.hs
+++ b/Data/X509/Ext.hs
@@ -13,6 +13,8 @@
     , ExtBasicConstraints(..)
     , ExtKeyUsage(..)
     , ExtKeyUsageFlag(..)
+    , ExtExtendedKeyUsage(..)
+    , ExtKeyUsagePurpose(..)
     , ExtSubjectKeyId(..)
     , ExtSubjectAltName(..)
     , ExtAuthorityKeyId(..)
@@ -29,8 +31,9 @@
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Char8 as BC
 import Data.ASN1.Types
+import Data.ASN1.Parse
 import Data.ASN1.BitArray
-import Data.X509.Internal
+import Data.List (find)
 import Data.X509.ExtensionRaw
 import Data.X509.DistinguishedName
 import Control.Applicative
@@ -116,6 +119,41 @@
     extEncode (ExtKeyUsage flags) = [BitString $ flagsToBits flags]
     extDecode [BitString bits] = Right $ ExtKeyUsage $ bitsToFlags bits
     extDecode _ = Left "unknown sequence"
+
+data ExtKeyUsagePurpose =
+      KeyUsagePurpose_ServerAuth
+    | KeyUsagePurpose_ClientAuth
+    | KeyUsagePurpose_CodeSigning
+    | KeyUsagePurpose_EmailProtection
+    | KeyUsagePurpose_TimeStamping
+    | KeyUsagePurpose_OCSPSigning
+    | KeyUsagePurpose_Unknown OID
+    deriving (Show,Eq,Ord)
+
+extKeyUsagePurposedOID :: [(OID, ExtKeyUsagePurpose)]
+extKeyUsagePurposedOID =
+    [(keyUsagePurposePrefix 1, KeyUsagePurpose_ServerAuth)
+    ,(keyUsagePurposePrefix 2, KeyUsagePurpose_ClientAuth)
+    ,(keyUsagePurposePrefix 3, KeyUsagePurpose_CodeSigning)
+    ,(keyUsagePurposePrefix 4, KeyUsagePurpose_EmailProtection)
+    ,(keyUsagePurposePrefix 8, KeyUsagePurpose_TimeStamping)
+    ,(keyUsagePurposePrefix 9, KeyUsagePurpose_OCSPSigning)]
+  where keyUsagePurposePrefix r = [1,3,6,1,5,5,7,3,r]
+
+data ExtExtendedKeyUsage = ExtExtendedKeyUsage [ExtKeyUsagePurpose]
+    deriving (Show,Eq)
+
+instance Extension ExtExtendedKeyUsage where
+    extOID = const [2,5,29,37]
+    extEncode (ExtExtendedKeyUsage purposes) =
+        [Start Sequence] ++ map (OID . lookupRev) purposes ++ [End Sequence]
+      where lookupRev (KeyUsagePurpose_Unknown oid) = oid
+            lookupRev kup = maybe (error "unknown key usage purpose") fst $ find ((==) kup . snd) extKeyUsagePurposedOID
+    extDecode l = ExtExtendedKeyUsage `fmap` (flip runParseASN1 l $ onNextContainer Sequence $ getMany $ do
+        n <- getNext
+        case n of
+            OID o -> return $ maybe (KeyUsagePurpose_Unknown o) id $ lookup o extKeyUsagePurposedOID
+            _     -> error "invalid content in extended key usage")
 
 -- | Provide a way to identify a public key by a short hash.
 data ExtSubjectKeyId = ExtSubjectKeyId B.ByteString
diff --git a/Tests/Tests.hs b/Tests/Tests.hs
--- a/Tests/Tests.hs
+++ b/Tests/Tests.hs
@@ -11,7 +11,7 @@
 import Control.Applicative
 import Control.Monad
 
-import Data.List (nub)
+import Data.List (nub, sort)
 import Data.ASN1.Types
 import Data.X509
 import qualified Crypto.Types.PubKey.RSA as RSA
@@ -93,8 +93,18 @@
 instance Arbitrary ExtKeyUsageFlag where
     arbitrary = elements $ enumFrom KeyUsage_digitalSignature
 instance Arbitrary ExtKeyUsage where
-    arbitrary = ExtKeyUsage . nub <$> listOf1 arbitrary
+    arbitrary = ExtKeyUsage . sort . nub <$> listOf1 arbitrary
 
+instance Arbitrary ExtKeyUsagePurpose where
+    arbitrary = elements [ KeyUsagePurpose_ServerAuth
+                         , KeyUsagePurpose_ClientAuth
+                         , KeyUsagePurpose_CodeSigning
+                         , KeyUsagePurpose_EmailProtection
+                         , KeyUsagePurpose_TimeStamping
+                         , KeyUsagePurpose_OCSPSigning ]
+instance Arbitrary ExtExtendedKeyUsage where
+    arbitrary = ExtExtendedKeyUsage . nub <$> listOf1 arbitrary
+
 instance Arbitrary Certificate where
     arbitrary = Certificate <$> pure 2
                             <*> arbitrary
@@ -130,10 +140,20 @@
   where got = fromASN1 oMarshalled
         oMarshalled = toASN1 o []
 
+property_extension_id :: (Show e, Eq e, Extension e) => e -> Bool
+property_extension_id e = case extDecode (extEncode e) of
+                                Left err -> error err
+                                Right v | v == e    -> True
+                                        | otherwise -> error ("expected " ++ show e ++ " got: " ++ show v)
+
 main = defaultMain
-    [ testGroup "asn1 objects unmarshall.marshall=id"
+    [ testGroup "marshall"
         [ testProperty "pubkey" (property_unmarshall_marshall_id :: PubKey -> Bool)
         , testProperty "signature alg" (property_unmarshall_marshall_id :: SignatureALG -> Bool)
+        , testGroup "extension"
+            [ testProperty "key-usage" (property_extension_id :: ExtKeyUsage -> Bool)
+            , testProperty "extended-key-usage" (property_extension_id :: ExtExtendedKeyUsage -> Bool)
+            ]
         , testProperty "extensions" (property_unmarshall_marshall_id :: Extensions -> Bool)
         , testProperty "certificate" (property_unmarshall_marshall_id :: Certificate -> Bool)
         , testProperty "crl" (property_unmarshall_marshall_id :: CRL -> Bool)
diff --git a/x509.cabal b/x509.cabal
--- a/x509.cabal
+++ b/x509.cabal
@@ -1,5 +1,5 @@
 Name:                x509
-Version:             1.4.6
+Version:             1.4.7
 Description:         X509 reader and writer
 License:             BSD3
 License-file:        LICENSE
