diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
 # Change log for "tls"
 
+## Version 2.4.6
+
+* Accept crypton 2.1, which made `ChaChaPoly1305.initialize` total by
+  taking a checked key rather than any `ByteArrayAccess`.  The ChaCha20
+  bulk cipher now goes through `aeadChacha20poly1305Init` and the AEAD
+  interface, as the AES ciphers beside it already did.  That function has
+  one type across every crypton this package accepts, so the bound stays
+  `>=1.1.2 && <2.2` and nobody is forced to move.  The two are the same
+  computation: crypton's AEAD model for this cipher is `finalizeAAD .
+  appendAAD`, then encrypt or decrypt, then the whole sixteen-byte
+  Poly1305 tag whatever length is asked of it.
+
 ## Version 2.4.5
 
 * Fix the TLS 1.3 0-RTT session tests racing the NewSessionTicket.
diff --git a/Network/TLS/Extra/Cipher.hs b/Network/TLS/Extra/Cipher.hs
--- a/Network/TLS/Extra/Cipher.hs
+++ b/Network/TLS/Extra/Cipher.hs
@@ -73,7 +73,6 @@
 import qualified Crypto.Cipher.ChaChaPoly1305 as ChaChaPoly1305
 import Crypto.Cipher.Types hiding (Cipher, cipherName)
 import Crypto.Error
-import qualified Crypto.MAC.Poly1305 as Poly1305
 import Crypto.System.CPU
 import qualified Data.ByteString as B
 import Data.Tuple (swap)
@@ -690,23 +689,20 @@
 noFail :: CryptoFailable a -> a
 noFail = throwCryptoError
 
+-- Through the AEAD interface rather than the state directly, as the AES
+-- ciphers above do.  The two are the same computation -- crypton's AEAD model
+-- for this cipher is finalizeAAD . appendAAD, then encrypt or decrypt, then
+-- the whole sixteen-byte Poly1305 tag whatever length is asked of it -- but
+-- aeadChacha20poly1305Init has one type across every crypton this package
+-- accepts, where the lower-level initialize does not: crypton 2.1 made it
+-- total, taking a checked Key rather than any ByteArrayAccess.
 chacha20poly1305 :: BulkDirection -> BulkKey -> BulkAEAD
 chacha20poly1305 BulkEncrypt key nonce =
-    let st = noFail (ChaChaPoly1305.nonce12 nonce >>= ChaChaPoly1305.initialize key)
-     in ( \input ad ->
-            let st2 = ChaChaPoly1305.finalizeAAD (ChaChaPoly1305.appendAAD ad st)
-                (output, st3) = ChaChaPoly1305.encrypt input st2
-                Poly1305.Auth tag = ChaChaPoly1305.finalize st3
-             in (output, AuthTag tag)
-        )
+    let aeadIni = noFail (ChaChaPoly1305.aeadChacha20poly1305Init key nonce)
+     in (\input ad -> swap $ aeadSimpleEncrypt aeadIni ad input 16)
 chacha20poly1305 BulkDecrypt key nonce =
-    let st = noFail (ChaChaPoly1305.nonce12 nonce >>= ChaChaPoly1305.initialize key)
-     in ( \input ad ->
-            let st2 = ChaChaPoly1305.finalizeAAD (ChaChaPoly1305.appendAAD ad st)
-                (output, st3) = ChaChaPoly1305.decrypt input st2
-                Poly1305.Auth tag = ChaChaPoly1305.finalize st3
-             in (output, AuthTag tag)
-        )
+    let aeadIni = noFail (ChaChaPoly1305.aeadChacha20poly1305Init key nonce)
+     in (\input ad -> simpleDecrypt aeadIni ad input 16)
 
 ----------------------------------------------------------------
 
diff --git a/tls.cabal b/tls.cabal
--- a/tls.cabal
+++ b/tls.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.0
 name:               tls
-version:            2.4.5
+version:            2.4.6
 license:            BSD3
 license-file:       LICENSE
 copyright:          Vincent Hanquez <vincent@snarc.org>
@@ -122,7 +122,7 @@
         base16-bytestring,
         bytestring >=0.10 && <0.13,
         cereal >=0.5.3 && <0.6,
-        crypton >=1.1.2 && <2.1,
+        crypton >=1.1.2 && <2.2,
         crypton-asn1-encoding >= 0.10.0 && < 0.11,
         crypton-asn1-types >= 0.4.1 && < 0.5,
         crypton-x509 >=1.9 && <1.10,
