diff --git a/automotive-cse.cabal b/automotive-cse.cabal
--- a/automotive-cse.cabal
+++ b/automotive-cse.cabal
@@ -1,6 +1,6 @@
 
 name:                automotive-cse
-version:             0.1.3.1
+version:             0.1.4.0
 synopsis:            Automotive CSE emulation
 description:         This package includes Cryptography Security Engine (CSE)
                      codec emulation for automotive things.
diff --git a/src/Codec/Automotive/CSE/Internal.hs b/src/Codec/Automotive/CSE/Internal.hs
--- a/src/Codec/Automotive/CSE/Internal.hs
+++ b/src/Codec/Automotive/CSE/Internal.hs
@@ -2,7 +2,7 @@
 -- CSE (Cryptographic Service Engine) emulation implementation
 module Codec.Automotive.CSE.Internal (
   M1, unM1, makeM1, extractM1,
-  M2, unM2, makeM2,
+  M2, unM2, makeM2, extractM2,
   M3, unM3, makeM3,
   M4, unM4, makeM4, extractM4, makeM4', extractM4',
   M5, unM5, makeM5,
@@ -226,6 +226,18 @@
 
 unM2 :: M2 -> ByteString
 unM2 (M2 m2) = m2
+
+extractM2 :: K1
+          -> M2
+          -> (Word32, Word8, KeyAuthUse NotAuth)
+extractM2 (DerivedCipher k1) (M2 m2) =
+    (fromIntegral $ b64 `shiftR` 36,
+     fromIntegral $ b64 `shiftR` 30 .&. 0x3f,
+     key)
+  where
+    (dbits, rawKey) = BS.splitAt 16 $ cbcDecrypt k1 nullIV m2
+    b64 = either (error . ("extractM2: " ++)) id $ runGet getWord64be dbits
+    key =  maybe (error "extractM2: wrong M2 length?") id $ makeKeyAuthUse rawKey
 
 newtype M3 = M3 ByteString deriving Eq
 
diff --git a/test/Iso.hs b/test/Iso.hs
--- a/test/Iso.hs
+++ b/test/Iso.hs
@@ -7,8 +7,8 @@
 import Test.QuickCheck (Arbitrary (..), choose)
 
 import Codec.Automotive.CSE
-  (UID, makeUID, M1, makeM1, extractM1, M4, makeM4, extractM4,
-   KeyAuthUse, makeKeyAuthUse, derivedCipher, K3, K3', makeK3)
+  (UID, makeUID, M1, makeM1, extractM1, M2, makeM2, extractM2, M4, makeM4, extractM4,
+   KeyAuthUse, makeKeyAuthUse, derivedCipher, K1, K1', makeK1, K3, K3', makeK3)
 
 import Control.Applicative ((<$>), (<*>))
 import Control.Monad (replicateM)
@@ -28,6 +28,9 @@
 instance Arbitrary UID where
   arbitrary = fromJust . makeUID . BS.pack <$> replicateM 15 arbitrary
 
+instance Arbitrary K1' where
+  arbitrary = makeK1 <$> arbitrary
+
 instance Arbitrary K3' where
   arbitrary = makeK3 <$> arbitrary
 
@@ -38,6 +41,18 @@
     <*> (unKeyID <$> arbitrary)
     <*> (unKeyID <$> arbitrary)
 
+newtype GenM2 = GenM2 (K1 -> M2)
+
+instance Show GenM2 where
+  show = const "GenM2"
+
+instance Arbitrary GenM2 where
+  arbitrary = do
+    c     <-  choose (0, 2^(28 :: Int) - 1)
+    f     <-  choose (0, 2^(6 :: Int) - 1)
+    key   <-  arbitrary
+    return . GenM2 $ \k1 -> makeM2 k1 c f key
+
 newtype GenM4 = GenM4 (K3 -> M4)
 
 instance Show GenM4 where
@@ -55,6 +70,12 @@
 isoM1 m1 = makeM1 uid kid akid == m1
   where (uid, kid, akid) = extractM1 m1
 
+isoM2 :: K1' -> GenM2 -> Bool
+isoM2 k1' (GenM2 g) = makeM2 k1 c f key == m2
+  where (c, f, key) = extractM2 k1 m2
+        k1 = derivedCipher k1'
+        m2 = g k1
+
 isoM4 :: K3' -> GenM4 -> Bool
 isoM4 k3' (GenM4 g) = makeM4 k3 uid kid akid c == m4
   where ((uid, kid, akid), c) = extractM4 k3 m4
@@ -64,5 +85,6 @@
 tests :: [Test]
 tests =
   [ qcTest "iso - M1 extract make" isoM1
+  , qcTest "iso - M2 extract make" isoM2
   , qcTest "iso - M4 extract make" isoM4
   ]
