diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
 # Changelog
 
+- 0.3.0 (2025-12-27)
+  * Updates the poly1305 dependency to a version that uses ppad-fixed for
+    fixed-width words and constant-time primitives internally. Also swaps
+    a naïve ByteString equality check out for a constant-time version.
+
 - 0.2.0 (2025-06-21)
   * The 'encrypt' and 'decrypt' functions are now total, returning 'Left
     InvalidKey', 'Left InvalidNonce', or 'Left InvalidMAC' values when
diff --git a/lib/Crypto/AEAD/ChaCha20Poly1305.hs b/lib/Crypto/AEAD/ChaCha20Poly1305.hs
--- a/lib/Crypto/AEAD/ChaCha20Poly1305.hs
+++ b/lib/Crypto/AEAD/ChaCha20Poly1305.hs
@@ -28,6 +28,7 @@
 import qualified Crypto.Cipher.ChaCha20 as ChaCha20
 import qualified Crypto.MAC.Poly1305 as Poly1305
 import Data.Bits ((.>>.))
+import qualified Data.Bits as B
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Internal as BI
 import Data.Word (Word64)
@@ -36,6 +37,13 @@
 fi = fromIntegral
 {-# INLINE fi #-}
 
+-- constant-time equality comparison on bytestrings
+ct_eq :: BS.ByteString -> BS.ByteString -> Bool
+ct_eq a@(BI.PS _ _ la) b@(BI.PS _ _ lb)
+  | la /= lb = False
+  | otherwise = BS.foldl' (B..|.) 0 (BS.packZipWith B.xor a b) == 0
+{-# INLINE ct_eq #-}
+
 -- little-endian bytestring encoding
 unroll :: Word64 -> BS.ByteString
 unroll i = case i of
@@ -72,10 +80,11 @@
   | otherwise = BS.replicate (16 - l `rem` 16) 0
 {-# INLINE pad16 #-}
 
+-- | Error values.
 data Error =
-    InvalidKey
-  | InvalidNonce
-  | InvalidMAC
+    InvalidKey    -- ^ the provided key was not 256 bits long
+  | InvalidNonce  -- ^ the provided nonce was not 96 bits long
+  | InvalidMAC    -- ^ the provided MAC does not authenticate the ciphertext
   deriving (Eq, Show)
 
 -- RFC8439 2.8
@@ -143,7 +152,7 @@
       case Poly1305.mac otk md3 of
         Nothing -> Left InvalidKey
         Just tag
-          | mac == tag -> case ChaCha20.cipher key 1 nonce cip of
+          | ct_eq mac tag -> case ChaCha20.cipher key 1 nonce cip of
               Left ChaCha20.InvalidKey -> Left InvalidKey
               Left ChaCha20.InvalidNonce -> Left InvalidNonce
               Right v -> pure v
diff --git a/ppad-aead.cabal b/ppad-aead.cabal
--- a/ppad-aead.cabal
+++ b/ppad-aead.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-aead
-version:            0.2.0
+version:            0.3.0
 synopsis:           A pure AEAD-ChaCha20-Poly1305 construction
 license:            MIT
 license-file:       LICENSE
@@ -30,7 +30,7 @@
       base >= 4.9 && < 5
     , bytestring >= 0.9 && < 0.13
     , ppad-chacha >= 0.2 && < 0.3
-    , ppad-poly1305 >= 0.3 && < 0.4
+    , ppad-poly1305 >= 0.4 && < 0.5
 
 test-suite aead-tests
   type:                exitcode-stdio-1.0
