diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,4 +1,19 @@
-zip-archive 0.4.3
+zip-archive 0.4.3.1
+
+  * Use streaming decompress to identify extent of compressed data (#66).
+    This fixes a problem that arises for local files with bit 3
+    of the general purpose bit flag set. In this case, we don't
+    get information up front about the size of the compressed
+    data.  So how do we know where the compressed data ends?
+    Previously, we tried to determine this by looking for the
+    signature of the data descriptor. But the data descriptor doesn't
+    always HAVE a signature, and it is also possible for signatures to
+    occur accidentally in the compressed data itself (#65).
+    Instead, we now use the streaming decompression interface from
+    zlib's Internal module to identify where the compressed data
+    ends. Fixes both #65 and #25.
+
+    zip-archive 0.4.3
 
   * Improve code for retrieving compressed data of unknown length (#63).
     Do not assume we'll have the signature 0x08074b50 that is
diff --git a/src/Codec/Archive/Zip.hs b/src/Codec/Archive/Zip.hs
--- a/src/Codec/Archive/Zip.hs
+++ b/src/Codec/Archive/Zip.hs
@@ -101,8 +101,6 @@
 import Data.Maybe (fromJust)
 #endif
 
-import GHC.Int (Int64)
-
 -- from bytestring
 import qualified Data.ByteString as S
 import qualified Data.ByteString.Lazy as B
@@ -114,8 +112,11 @@
 
 -- from zlib
 import qualified Codec.Compression.Zlib.Raw as Zlib
+import qualified Codec.Compression.Zlib.Internal as ZlibInt
 import System.IO.Error (isAlreadyExistsError)
 
+-- import Debug.Trace
+
 manySig :: Word32 -> Get a -> Get [a]
 manySig sig p = do
     sig' <- lookAhead getWord32le
@@ -768,7 +769,11 @@
   getWord32le >>= ensure (== 0x04034b50)
   skip 2  -- version
   bitflag <- getWord16le
-  skip 2  -- compressionMethod
+  rawCompressionMethod <- getWord16le
+  compressionMethod <- case rawCompressionMethod of
+                        0 -> return NoCompression
+                        8 -> return Deflate
+                        _ -> fail $ "Unknown compression method " ++ show rawCompressionMethod
   skip 2  -- last mod file time
   skip 2  -- last mod file date
   skip 4  -- crc32
@@ -780,12 +785,13 @@
   extraFieldLength <- getWord16le
   skip (fromIntegral fileNameLength)  -- filename
   skip (fromIntegral extraFieldLength) -- extra field
-  compressedData <- if bitflag .&. 0O10 == 0
+  compressedData <-
+    if bitflag .&. 0O10 == 0
       then getLazyByteString (fromIntegral compressedSize)
       else -- If bit 3 of general purpose bit flag is set,
            -- then we need to read until we get to the
            -- data descriptor record.
-           do raw <- getCompressedData
+           do raw <- getCompressedData compressionMethod
               sig <- lookAhead getWord32le
               when (sig == 0x08074b50) $ skip 4
               skip 4 -- crc32
@@ -793,43 +799,12 @@
               skip 4 -- uncompressed size
               if fromIntegral cs == B.length raw
                  then return raw
-                 else fail "Content size mismatch in data descriptor record"
+                 else fail $ printf
+                       ("Content size mismatch in data descriptor record: "
+                         <> "expected %d, got %d bytes")
+                       cs (B.length raw)
   return (fromIntegral offset, compressedData)
 
--- Move forward over data (not consuming it) until:
--- - start of the next local file header
--- - start of archive decryption header
--- Then back up 12 bytes (the data description record)
--- and possibly 4 more bytes
--- (conventional but not required sig 0x08074b50 for data description record).
-getCompressedData :: Get B.ByteString
-getCompressedData = do
-  numbytes <- lookAhead $ findEnd 0
-  getLazyByteString numbytes
- where
-   chunkSize :: Int64
-   chunkSize = 16384
-   findEnd :: Int64 -> Get Int64
-   findEnd n = do
-     sig <- lookAhead getWord32le
-     case sig of
-       0x08074b50 -> skip 4 >> return n
-       0x04034b50 -> -- sig for local file header
-        return (n - 12) -- rewind past data description
-       0x02014b50 -> -- sig for file header
-        return (n - 12) -- rewind past data description
-       0x06054b50 -> -- sig for end of central directory header
-        return (n - 12) -- rewind past data description
-       x | x .&. 0xFF == 0x50 -> skip 1 >> findEnd (n + 1)
-       _ -> do bs <- lookAhead $ getLazyByteString chunkSize
-                             <|> getRemainingLazyByteString
-               let bsLen = B.length bs
-               let mbIdx = B.elemIndex 0x50 bs
-               case mbIdx of
-                 Nothing -> skip (fromIntegral bsLen) >> findEnd (n + bsLen)
-                 Just 0  -> skip 1 >> findEnd (n + 1)
-                 Just idx -> skip (fromIntegral idx) >> findEnd (n + idx)
-
 putLocalFile :: Entry -> Put
 putLocalFile f = do
   putWord32le 0x04034b50
@@ -992,3 +967,56 @@
 
 fromString :: String -> B.ByteString
 fromString = TL.encodeUtf8 . TL.pack
+
+data DecompressResult =
+    DecompressSuccess B.ByteString -- bytes remaining
+      -- (we just discard decompressed chunks, because we only
+      -- want to know where the compressed data ends)
+  | DecompressFailure ZlibInt.DecompressError
+
+getCompressedData :: CompressionMethod -> Get B.ByteString
+getCompressedData NoCompression = do
+  -- we assume there will be a signature on the data descriptor,
+  -- otherwise we have no way of identifying where the data ends!
+  -- The signature 0x08074b50 is commonly used but not required by spec.
+  let findSigPos = do
+        w1 <- getWord8
+        if w1 == 0x50
+           then do
+             w2 <- getWord8
+             if w2 == 0x4b
+                then do
+                  w3 <- getWord8
+                  if w3 == 0x07
+                     then do
+                       w4 <- getWord8
+                       if w4 == 0x08
+                          then (\x -> x - 4) <$> bytesRead
+                          else findSigPos
+                     else findSigPos
+                else findSigPos
+           else findSigPos
+  pos <- bytesRead
+  sigpos <- lookAhead findSigPos <|>
+              fail "getCompressedData can't find data descriptor signature"
+  let compressedBytes = sigpos - pos
+  getLazyByteString compressedBytes
+getCompressedData Deflate = do
+  remainingBytes <- lookAhead getRemainingLazyByteString
+  let result = ZlibInt.foldDecompressStreamWithInput
+                (\_bs res -> res)
+                DecompressSuccess
+                DecompressFailure
+                (ZlibInt.decompressST ZlibInt.rawFormat
+                 ZlibInt.defaultDecompressParams{
+                     ZlibInt.decompressAllMembers = False })
+                remainingBytes
+  case result of
+    DecompressFailure err -> fail (show err)
+    DecompressSuccess afterCompressedBytes ->
+      -- Consume the compressed bytes; we don't do anything with
+      -- the decompressed chunks. We are just decompressing as a
+      -- way of finding where the compressed data ends.
+      getLazyByteString
+        (fromIntegral (B.length remainingBytes - B.length afterCompressedBytes))
+
diff --git a/zip-archive.cabal b/zip-archive.cabal
--- a/zip-archive.cabal
+++ b/zip-archive.cabal
@@ -1,5 +1,5 @@
 Name:                zip-archive
-Version:             0.4.3
+Version:             0.4.3.1
 Cabal-Version:       2.0
 Build-type:          Simple
 Synopsis:            Library for creating and modifying zip archives.
