diff --git a/Data/ASN1/BER.hs b/Data/ASN1/BER.hs
--- a/Data/ASN1/BER.hs
+++ b/Data/ASN1/BER.hs
@@ -13,6 +13,7 @@
 	, ASN1ConstructionType(..)
 
 	-- * enumeratee to transform between ASN1 and raw
+	, enumReadRawRepr
 	, enumReadRaw
 	, enumWriteRaw
 
@@ -23,12 +24,17 @@
 	-- * iterate over common representation to an ASN1 stream
 	, iterateFile
 	, iterateByteString
+	, iterateByteStringRepr
 	, iterateEvents
+	, iterateEventsRepr
 
 	-- * BER serialize functions
+	, decodeASN1EventsRepr
 	, decodeASN1Events
 	, encodeASN1Events
+
 	, decodeASN1Stream
+	, decodeASN1StreamRepr
 	, encodeASN1Stream
 
 	-- * BER serialize functions, deprecated
@@ -60,30 +66,47 @@
 decodeConstruction (ASN1Header Universal 0x11 _ _) = Set
 decodeConstruction (ASN1Header c t _ _)            = Container c t
 
-{- | enumReadRaw is an enumeratee from raw events to asn1 -}
-enumReadRaw :: Monad m => Enumeratee Raw.ASN1Event ASN1 m a
-enumReadRaw = E.checkDone $ \k -> k (E.Chunks []) >>== loop []
+{- | enumerate from 'Raw.ASN1Event' to an 'ASN1Repr' (ASN1 augmented by a list of raw asn1 events)
+ -}
+enumReadRawRepr :: Monad m => Enumeratee Raw.ASN1Event ASN1Repr m a
+enumReadRawRepr = E.checkDone $ \k -> k (E.Chunks []) >>== loop []
 	where
 		loop l = E.checkDone $ go l
 		go l k = E.head >>= \x -> case x of
-			Nothing                  ->
-				if l == [] then  k (E.Chunks []) >>== return else E.throwError (Raw.ASN1ParsingPartial)
-			Just Raw.ConstructionEnd ->
-				k (E.Chunks [head l]) >>== loop (tail l)
-			Just (Raw.Header hdr@(ASN1Header _ _ True _)) -> E.head >>= \z -> case z of
-				Nothing                    -> E.throwError (Raw.ASN1ParsingFail "expecting construction, got EOF")
-				Just Raw.ConstructionBegin ->
-					let ctype = decodeConstruction hdr in
-					k (E.Chunks [Start ctype]) >>== loop (End ctype : l)
-				Just _                     -> E.throwError (Raw.ASN1ParsingFail "expecting construction")
-			Just (Raw.Header hdr@(ASN1Header _ _ False _)) -> E.head >>= \z -> case z of
-				Nothing -> E.throwError (Raw.ASN1ParsingFail "expecting primitive, got EOF")
-				Just (Raw.Primitive p) ->
-					let (Right pr) = decodePrimitive hdr p in
-					k (E.Chunks [pr]) >>== loop l
-				Just _  -> E.throwError (Raw.ASN1ParsingFail "expecting primitive")
-			Just _ -> E.throwError (Raw.ASN1ParsingFail "boundary not a header")
+			Nothing -> if l == [] then k (E.Chunks []) >>== return else E.throwError (Raw.ASN1ParsingPartial)
+			Just el -> p l k el
 
+		{- on construction end, we pop the list context -}
+		p l k Raw.ConstructionEnd = k (E.Chunks [head l]) >>== loop (tail l)
+
+		{- on header with construction, we pop the next element in the enumerator and
+		 - expect a ConstructionBegin. the list context is prepended by the new construction -}
+		p l k el@(Raw.Header hdr@(ASN1Header _ _ True _)) = E.head >>= \z -> case z of
+			Just el2@Raw.ConstructionBegin ->
+				let ctype = decodeConstruction hdr in
+				k (E.Chunks [(Start ctype, [el,el2])]) >>== loop ((End ctype,[Raw.ConstructionEnd]) : l)
+			Just _  -> E.throwError (Raw.ASN1ParsingFail "expecting construction")
+			Nothing -> E.throwError (Raw.ASN1ParsingFail "expecting construction, got EOF")
+
+		{- on header with primtive, we pop the next element in the enumerator and
+		 - expect a Primitive -}
+		p l k el@(Raw.Header hdr@(ASN1Header _ _ False _)) = E.head >>= \z -> case z of
+			Just el2@(Raw.Primitive prim) ->
+				let (Right pr) = decodePrimitive hdr prim in
+				k (E.Chunks [(pr, [el,el2])]) >>== loop l
+			Just _  -> E.throwError (Raw.ASN1ParsingFail "expecting primitive")
+			Nothing -> E.throwError (Raw.ASN1ParsingFail "expecting primitive, got EOF")
+
+		p _ _ _ = E.throwError (Raw.ASN1ParsingFail "boundary not a header")
+
+{- | enumeratee from 'Raw.ASN1Event to 'ASN1'
+ -
+ - it's the enumerator equivalent:
+ - @enumReadRaw = map fst . enumReadRawRepr@
+ -}
+enumReadRaw :: Monad m => Enumeratee Raw.ASN1Event ASN1 m a
+enumReadRaw = \f -> E.joinI (enumReadRawRepr $$ (E.map fst f))
+
 {- | enumWriteRaw is an enumeratee from asn1 to raw events -}
 enumWriteRaw :: Monad m => Enumeratee ASN1 Raw.ASN1Event m a
 enumWriteRaw = \f -> E.joinI (enumWriteTree $$ (enumWriteTreeRaw f))
@@ -139,6 +162,11 @@
 enumReadBytes :: Monad m => Enumeratee ByteString ASN1 m a
 enumReadBytes = \f -> E.joinI (Raw.enumReadBytes $$ (enumReadRaw f))
 
+{-| enumReadBytes is an enumeratee converting from bytestring to ASN1
+  it transforms chunks of bytestring into chunks of ASN1 objects -}
+enumReadBytesRepr :: Monad m => Enumeratee ByteString ASN1Repr m a
+enumReadBytesRepr = \f -> E.joinI (Raw.enumReadBytes $$ (enumReadRawRepr f))
+
 {-| enumWriteBytes is an enumeratee converting from ASN1 to bytestring.
   it transforms chunks of ASN1 objects into chunks of bytestring  -}
 enumWriteBytes :: Monad m => Enumeratee ASN1 ByteString m a
@@ -152,10 +180,18 @@
 iterateByteString :: Monad m => L.ByteString -> Iteratee ASN1 m a -> m (Either SomeException a)
 iterateByteString bs p = E.run (E.enumList 1 (L.toChunks bs) $$ E.joinI $ enumReadBytes $$ p)
 
+{-| iterate over a bytestring using a list enumerator over each chunks -}
+iterateByteStringRepr :: Monad m => L.ByteString -> Iteratee ASN1Repr m a -> m (Either SomeException a)
+iterateByteStringRepr bs p = E.run (E.enumList 1 (L.toChunks bs) $$ E.joinI $ enumReadBytesRepr $$ p)
+
 {-| iterate over asn1 events using a list enumerator over each chunks -}
 iterateEvents :: Monad m => [Raw.ASN1Event] -> Iteratee ASN1 m a -> m (Either SomeException a)
 iterateEvents evs p = E.run (E.enumList 8 evs $$ E.joinI $ enumReadRaw $$ p)
 
+{-| iterate over asn1 events using a list enumerator over each chunks -}
+iterateEventsRepr :: Monad m => [Raw.ASN1Event] -> Iteratee ASN1Repr m a -> m (Either SomeException a)
+iterateEventsRepr evs p = E.run (E.enumList 8 evs $$ E.joinI $ enumReadRawRepr $$ p)
+
 {- helper to transform a Someexception from the enumerator to an ASN1Err if possible -}
 wrapASN1Err :: Either SomeException a -> Either ASN1Err a
 wrapASN1Err (Left err) = Left (maybe (ASN1ParsingFail "unknown") id $ fromException err)
@@ -165,9 +201,17 @@
 decodeASN1Events :: [Raw.ASN1Event] -> Either ASN1Err [ASN1]
 decodeASN1Events evs = wrapASN1Err $ runIdentity (iterateEvents evs E.consume)
 
+{-| decode a list of raw ASN1Events into a stream of ASN1Repr types -}
+decodeASN1EventsRepr :: [Raw.ASN1Event] -> Either ASN1Err [ASN1Repr]
+decodeASN1EventsRepr evs = wrapASN1Err $ runIdentity (iterateEventsRepr evs E.consume)
+
 {-| decode a lazy bytestring as an ASN1 stream -}
 decodeASN1Stream :: L.ByteString -> Either ASN1Err [ASN1]
 decodeASN1Stream l = wrapASN1Err $ runIdentity (iterateByteString l E.consume)
+
+{-| decode a lazy bytestring as an ASN1repr stream -}
+decodeASN1StreamRepr :: L.ByteString -> Either ASN1Err [ASN1Repr]
+decodeASN1StreamRepr l = wrapASN1Err $ runIdentity (iterateByteStringRepr l E.consume)
 
 {-| encode an ASN1 Stream as raw ASN1 Events -}
 encodeASN1Events :: [ASN1] -> Either ASN1Err [Raw.ASN1Event]
diff --git a/Data/ASN1/DER.hs b/Data/ASN1/DER.hs
--- a/Data/ASN1/DER.hs
+++ b/Data/ASN1/DER.hs
@@ -13,22 +13,29 @@
 	, ASN1ConstructionType(..)
 
 	-- * enumeratee to transform between ASN1 and raw
+	, enumReadRawRepr
 	, enumReadRaw
 	, enumWriteRaw
 
 	-- * enumeratee to transform between ASN1 and bytes
 	, enumReadBytes
+	, enumReadBytesRepr
 	, enumWriteBytes
 
 	-- * iterate over common representation to an ASN1 stream
 	, iterateFile
 	, iterateByteString
+	, iterateByteStringRepr
 	, iterateEvents
+	, iterateEventsRepr
 
 	-- * DER serialize functions
+	, decodeASN1EventsRepr
 	, decodeASN1Events
 	, encodeASN1Events
+
 	, decodeASN1Stream
+	, decodeASN1StreamRepr
 	, encodeASN1Stream
 
 	-- * DER serialize functions, deprecated
@@ -42,6 +49,7 @@
 import qualified Data.ASN1.Raw as Raw
 
 import Data.ASN1.Prim
+import Data.ASN1.Stream (ASN1Repr)
 import Data.ASN1.Types (ofStream, toStream, ASN1t)
 
 import qualified Data.ASN1.BER as BER
@@ -83,6 +91,10 @@
 enumReadRaw :: Monad m => Enumeratee Raw.ASN1Event ASN1 m a
 enumReadRaw = \f -> E.joinI (checkRawDER $$ BER.enumReadRaw f)
 
+{- | enumReadRawRepr is an enumeratee from raw events to asn1repr -}
+enumReadRawRepr :: Monad m => Enumeratee Raw.ASN1Event ASN1Repr m a
+enumReadRawRepr = \f -> E.joinI (checkRawDER $$ BER.enumReadRawRepr f)
+
 {- | enumWriteRaw is an enumeratee from asn1 to raw events -}
 enumWriteRaw :: Monad m => Enumeratee ASN1 Raw.ASN1Event m a
 enumWriteRaw = BER.enumWriteRaw
@@ -90,8 +102,13 @@
 {-| enumReadBytes is an enumeratee converting from bytestring to ASN1
   it transforms chunks of bytestring into chunks of ASN1 objects -}
 enumReadBytes :: Monad m => Enumeratee ByteString ASN1 m a
-enumReadBytes = \f -> E.joinI (Raw.enumReadBytes $$ (BER.enumReadRaw f))
+enumReadBytes = \f -> E.joinI (Raw.enumReadBytes $$ (enumReadRaw f))
 
+{-| enumReadBytes is an enumeratee converting from bytestring to ASN1
+  it transforms chunks of bytestring into chunks of ASN1 objects -}
+enumReadBytesRepr :: Monad m => Enumeratee ByteString ASN1Repr m a
+enumReadBytesRepr = \f -> E.joinI (Raw.enumReadBytes $$ (enumReadRawRepr f))
+
 {-| enumWriteBytes is an enumeratee converting from ASN1 to bytestring.
   it transforms chunks of ASN1 objects into chunks of bytestring  -}
 enumWriteBytes :: Monad m => Enumeratee ASN1 ByteString m a
@@ -105,10 +122,18 @@
 iterateByteString :: Monad m => L.ByteString -> Iteratee ASN1 m a -> m (Either SomeException a)
 iterateByteString bs p = E.run (E.enumList 1 (L.toChunks bs) $$ E.joinI $ enumReadBytes $$ p)
 
+{-| iterate over a bytestring using a list enumerator over each chunks -}
+iterateByteStringRepr :: Monad m => L.ByteString -> Iteratee ASN1Repr m a -> m (Either SomeException a)
+iterateByteStringRepr bs p = E.run (E.enumList 1 (L.toChunks bs) $$ E.joinI $ enumReadBytesRepr $$ p)
+
 {-| iterate over asn1 events using a list enumerator over each chunks -}
 iterateEvents :: Monad m => [Raw.ASN1Event] -> Iteratee ASN1 m a -> m (Either SomeException a)
 iterateEvents evs p = E.run (E.enumList 8 evs $$ E.joinI $ enumReadRaw $$ p)
 
+{-| iterate over asn1 events using a list enumerator over each chunks -}
+iterateEventsRepr :: Monad m => [Raw.ASN1Event] -> Iteratee ASN1Repr m a -> m (Either SomeException a)
+iterateEventsRepr evs p = E.run (E.enumList 8 evs $$ E.joinI $ enumReadRawRepr $$ p)
+
 {- helper to transform a Someexception from the enumerator to an ASN1Err if possible -}
 wrapASN1Err :: Either SomeException a -> Either ASN1Err a
 wrapASN1Err (Left err) = Left (maybe (ASN1ParsingFail "unknown") id $ fromException err)
@@ -118,9 +143,17 @@
 decodeASN1Events :: [Raw.ASN1Event] -> Either ASN1Err [ASN1]
 decodeASN1Events evs = wrapASN1Err $ runIdentity (iterateEvents evs E.consume)
 
+{-| decode a list of raw ASN1Events into a stream of ASN1Repr types -}
+decodeASN1EventsRepr :: [Raw.ASN1Event] -> Either ASN1Err [ASN1Repr]
+decodeASN1EventsRepr evs = wrapASN1Err $ runIdentity (iterateEventsRepr evs E.consume)
+
 {-| decode a lazy bytestring as an ASN1 stream -}
 decodeASN1Stream :: L.ByteString -> Either ASN1Err [ASN1]
 decodeASN1Stream l = wrapASN1Err $ runIdentity (iterateByteString l E.consume)
+
+{-| decode a lazy bytestring as an ASN1repr stream -}
+decodeASN1StreamRepr :: L.ByteString -> Either ASN1Err [ASN1Repr]
+decodeASN1StreamRepr l = wrapASN1Err $ runIdentity (iterateByteStringRepr l E.consume)
 
 {-| encode an ASN1 Stream as raw ASN1 Events -}
 encodeASN1Events :: [ASN1] -> Either ASN1Err [Raw.ASN1Event]
diff --git a/Data/ASN1/Stream.hs b/Data/ASN1/Stream.hs
--- a/Data/ASN1/Stream.hs
+++ b/Data/ASN1/Stream.hs
@@ -1,5 +1,6 @@
 module Data.ASN1.Stream
 	( ASN1(..)
+	, ASN1Repr
 	, ASN1ConstructionType(..)
 	, getConstructedEnd
 	) where
@@ -42,6 +43,11 @@
 	| Start ASN1ConstructionType
 	| End ASN1ConstructionType
 	deriving (Show, Eq)
+
+{- associate a list of asn1 event with an ASN1 type.
+ - it's sometimes required to know the exact byte sequence leading to an ASN1 type:
+ - eg: cryptographic signature -}
+type ASN1Repr = (ASN1, [ASN1Event])
 
 getConstructedEnd :: Int -> [ASN1] -> ([ASN1],[ASN1])
 getConstructedEnd _ xs@[]                = (xs, xs)
diff --git a/Tests.hs b/Tests.hs
--- a/Tests.hs
+++ b/Tests.hs
@@ -1,5 +1,3 @@
---{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
-
 import Test.QuickCheck
 import Text.Printf
 
@@ -145,6 +143,24 @@
 		, liftM UniversalString arbitrary
 		]
 
+newtype ASN1s = ASN1s [ASN1]
+
+instance Show ASN1s where
+	show (ASN1s x) = show x
+
+instance Arbitrary ASN1s where
+	arbitrary = do
+		x <- choose (0,5) :: Gen Int
+		z <- case x of
+			4 -> makeList Sequence
+			3 -> makeList Set
+			_ -> resize 2 $ listOf1 arbitrary
+		return $ ASN1s z
+		where
+			makeList str = do
+				(ASN1s l) <- arbitrary
+				return ([Start str] ++ l ++ [End str])
+
 instance Arbitrary T.ASN1t where
 	arbitrary = oneof
 		[ liftM T.Boolean arbitrary
@@ -192,6 +208,14 @@
 	where
 		enumWriteReadRaw = \f -> E.joinI (BER.enumWriteRaw $$ (BER.enumReadRaw f))
 
+prop_asn1_event_repr_id :: ASN1s -> Bool
+prop_asn1_event_repr_id (ASN1s l) =
+	case BER.encodeASN1Events l of
+		Left _       -> False
+		Right events -> case BER.decodeASN1EventsRepr events of
+			Left _       -> False
+			Right l2repr -> map fst l2repr == l && concat (map snd l2repr) == events
+
 prop_asn1_ber_marshalling_id :: T.ASN1t -> Bool
 prop_asn1_ber_marshalling_id v = (BER.decodeASN1 . BER.encodeASN1) v == Right v
 
@@ -211,5 +235,6 @@
 	run_test "marshalling header = id" prop_header_marshalling_id
 	run_test "marshalling event = id" prop_event_marshalling_id
 	run_test "marshalling asn1 stream = id" prop_asn1_event_marshalling_id
+	run_test "marshalling asn1 repr = id" prop_asn1_event_repr_id
 	run_test "marshalling asn1 BER type = id" prop_asn1_ber_marshalling_id
 	run_test "marshalling asn1 DER type = id" prop_asn1_der_marshalling_id
diff --git a/asn1-data.cabal b/asn1-data.cabal
--- a/asn1-data.cabal
+++ b/asn1-data.cabal
@@ -1,5 +1,5 @@
 Name:                asn1-data
-Version:             0.4.2
+Version:             0.4.3
 Description:
     ASN1 data reader and writer in raw form with supports for high level forms of ASN1 (BER, CER and DER).
     .
