diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,8 @@
+### 0.5.1.0
+
+- Hide the constructor of *CertId*.
+- Refactor function *getOCSPResponseVerificationData'*.
+
 ### 0.5.0.0
 
 - Migrate from *cryptohash-sha1* to *crypton* and *ram*.
diff --git a/Data/X509/OCSP.hs b/Data/X509/OCSP.hs
--- a/Data/X509/OCSP.hs
+++ b/Data/X509/OCSP.hs
@@ -18,7 +18,7 @@
 
 module Data.X509.OCSP (
     -- * Shared data
-                       CertId (..)
+                       CertId
     -- * OCSP request
                       ,encodeOCSPRequestASN1
                       ,encodeOCSPRequest
@@ -57,28 +57,11 @@
 pattern OidBasicOCSPResponse :: OID
 pattern OidBasicOCSPResponse = [1, 3, 6, 1, 5, 5, 7, 48, 1, 1]
 
-derLWidth :: Word8 -> Int64
-derLWidth x | testBit x 7 = succ $ fromIntegral $ x .&. 0x7f
-            | otherwise = 1
-
-issuerDNHash :: HashAlgorithm a => Certificate -> Digest a
-issuerDNHash cert = hashlazy $ encodeASN1 DER dn
-    where dn = toASN1 (certIssuerDN cert) []
-{-# SPECIALIZE issuerDNHash :: Certificate -> Digest SHA1 #-}
-
-pubKeyHash :: HashAlgorithm a => Certificate -> Digest a
-pubKeyHash cert = hashlazy $ L.drop (succ $ derLWidth $ L.head pk) pk
-    where pk = case toASN1 (certPubKey cert) [] of
-                   Start Sequence
-                     : Start Sequence
-                     : OID _
-                     : (skipCurrentContainer -> v@BitString {} : _) ->
-                         L.drop 1 $ encodeASN1 DER $ pure v
-                   _ -> error "bad pubkey sequence"
-{-# SPECIALIZE pubKeyHash :: Certificate -> Digest SHA1 #-}
-
 -- | Certificate Id.
 --
+-- Corresponds to /CertId/ from /rfc6960/. Contains /hashAlgorithm/,
+-- /issuerNameHash/, /issuerKeyHash/, and /serialNumber/.
+--
 -- This data is used when building OCSP requests and parsing OCSP responses.
 data CertId = CertId { certIdHashAlgorithm :: OID
                        -- ^ Value of /hashAlgorithm/ as defined in /rfc6960/
@@ -108,19 +91,44 @@
     fromASN1 (Asn1CertId alg h1 h2 sn xs) = Right (CertId alg h1 h2 sn, xs)
     fromASN1 _ = Left "fromASN1: CertId: unexpected format"
 
+derLWidth :: Word8 -> Int64
+derLWidth x | testBit x 7 = succ $ fromIntegral $ x .&. 0x7f
+            | otherwise = 1
+
+issuerDNHash :: HashAlgorithm a => Certificate -> Digest a
+issuerDNHash cert = hashlazy $ encodeASN1 DER dn
+    where dn = toASN1 (certIssuerDN cert) []
+{-# SPECIALIZE issuerDNHash :: Certificate -> Digest SHA1 #-}
+
+pubKeyHash :: HashAlgorithm a => Certificate -> Digest a
+pubKeyHash cert = hashlazy $ L.drop (succ $ derLWidth $ L.head pk) pk
+    where pk = case toASN1 (certPubKey cert) [] of
+                   Start Sequence
+                     : Start Sequence
+                     : OID _
+                     : (skipCurrentContainer -> v@BitString {} : _) ->
+                         L.drop 1 $ encodeASN1 DER $ pure v
+                   _ -> error "bad pubkey sequence"
+{-# SPECIALIZE pubKeyHash :: Certificate -> Digest SHA1 #-}
+
+toCertId :: Certificate -> Certificate -> CertId
+toCertId cert issuerCert =
+    let h1 = BA.convert $ issuerDNHash @SHA1 cert
+        h2 = BA.convert $ pubKeyHash @SHA1 issuerCert
+        sn = certSerial cert
+    in CertId OidAlgorithmSHA1 h1 h2 sn
+
 -- | Build and encode OCSP request in ASN.1 format.
 --
 -- The returned value contains the encoded request and an object of type
--- t'CertId' with hashes calculated by the SHA1 algorithm.
+-- t'CertId' with hashes calculated by the SHA1 algorithm. The returned
+-- /CertId/ must be passed in 'decodeOCSPResponse'.
 encodeOCSPRequestASN1
     :: Certificate              -- ^ Certificate
     -> Certificate              -- ^ Issuer certificate
     -> ([ASN1], CertId)
 encodeOCSPRequestASN1 cert issuerCert =
-    let h1 = BA.convert $ issuerDNHash @SHA1 cert
-        h2 = BA.convert $ pubKeyHash @SHA1 issuerCert
-        sn = certSerial cert
-        certId = CertId OidAlgorithmSHA1 h1 h2 sn
+    let certId = toCertId cert issuerCert
     in ( Start Sequence
          : Start Sequence
          : Start Sequence
@@ -132,7 +140,8 @@
 -- | Build and encode OCSP request in ASN.1\/DER format.
 --
 -- The returned value contains the encoded request and an object of type
--- t'CertId' with hashes calculated by the SHA1 algorithm.
+-- t'CertId' with hashes calculated by the SHA1 algorithm. The returned
+-- /CertId/ must be passed in 'decodeOCSPResponse'.
 encodeOCSPRequest
     :: Certificate              -- ^ Certificate
     -> Certificate              -- ^ Issuer certificate
@@ -191,7 +200,7 @@
 -- The /Right/ value with /Nothing/ gets returned on unexpected ASN.1 contents.
 decodeOCSPResponse
     :: CertId                   -- ^ Certificate Id
-    -> L.ByteString             -- ^ OCSP response
+    -> L.ByteString             -- ^ Raw encoded OCSP response
     -> Either ASN1Error (Maybe OCSPResponse)
 decodeOCSPResponse certId resp = decodeASN1 DER resp >>= \case
     [ Start Sequence
@@ -314,10 +323,9 @@
     :: [ASN1]                   -- ^ OCSP response payload
     -> Maybe OCSPResponseVerificationData
 getOCSPResponseVerificationData' (Start Sequence : Start Sequence : c1)
-    | (resp, Start Sequence : c2) <- getConstructedEnd 0 c1
-    , (alg, BitString (BitArray _ sig) : c3) <- getConstructedEnd 0 c2 = do
-        (alg', []) <- fromASN1' $ wrapInSequence alg
-        let der = encodeASN1' DER $ wrapInSequence resp
+    | (resp, c2) <- getConstructedEnd 0 c1
+    , Right (alg, BitString (BitArray _ sig) : c3) <- fromASN1 c2 = do
+        let der = encodeASN1' DER $ Start Sequence : resp ++ [End Sequence]
         case c3 of
             [End Sequence] -> Just []
             _ | Start (Container Context 0)
@@ -326,23 +334,17 @@
                       getCurrentContainerContents c3 ->
                           reverse <$> collectCerts certs []
               | otherwise -> Nothing
-            >>= Just . OCSPResponseVerificationData der alg' sig
+            >>= Just . OCSPResponseVerificationData der alg sig
     where collectCerts (Start Sequence : c4) certs
-              | (Start Sequence : cert, c5) <- getConstructedEnd 0 c4
-              , (cert', Start Sequence : c6) <- getConstructedEnd 0 cert
-              , (alg, [BitString (BitArray _ sig)]) <-
-                  getConstructedEnd 0 c6 = do
-                      (alg', []) <- fromASN1' $ wrapInSequence alg
-                      (cert'', []) <- fromASN1' cert'
-                      collectCerts c5 $
-                          ( Signed cert'' alg' sig
-                          , encodeASN1' DER $ wrapInSequence cert'
-                          ) : certs
+              | (c5@(Start Sequence : c6), next) <- getConstructedEnd 0 c4
+              , Right (cert, End Sequence : c7) <- fromASN1 c6
+              , Right (alg, [BitString (BitArray _ sig)]) <- fromASN1 c7 =
+                  collectCerts next $
+                      (Signed cert alg sig, encodeASN1' DER c5) : certs
           collectCerts [End Sequence, End (Container Context 0)] certs =
               Just certs
           collectCerts _ _ =
               Nothing
-          wrapInSequence = (Start Sequence :) . (++ [End Sequence])
 getOCSPResponseVerificationData' _ = Nothing
 
 getCurrentContainerContents :: [ASN1] -> [ASN1]
@@ -350,7 +352,4 @@
 
 skipCurrentContainer :: [ASN1] -> [ASN1]
 skipCurrentContainer = snd . getConstructedEnd 0
-
-fromASN1' :: ASN1Object a => [ASN1] -> Maybe (a, [ASN1])
-fromASN1' = either (const Nothing) Just . fromASN1
 
diff --git a/x509-ocsp.cabal b/x509-ocsp.cabal
--- a/x509-ocsp.cabal
+++ b/x509-ocsp.cabal
@@ -1,7 +1,7 @@
 cabal-version:          2.4
 
 name:                   x509-ocsp
-version:                0.5.0.0
+version:                0.5.1.0
 synopsis:               Basic X509 OCSP implementation
 description:            Build X509 OCSP requests and parse responses
 homepage:               https://github.com/lyokha/x509-ocsp
