ChaCha20-Poly1305 Cipher (RFC 8439)
Encrypt and decrypt with AEAD_CHACHA20_POLY1305 in your browser, with the Poly1305 one-time key and the counter split shown.
How to use
- Load the RFC 8439 vector to see a case with a published answer, then change one byte and watch the tag move.
- For your own data, press random for a fresh key and nonce, enter the plaintext and any additional data, and encrypt.
- To check something you received, switch to decrypt and paste the ciphertext and tag — a plaintext appears only if the tag verifies.
- Read the one-time key and the counter note when comparing against an implementation you are writing; that is where hand-rolled versions diverge.
About this tool
ShowHide
Seal a message with ChaCha20-Poly1305 or open one and verify its tag, and see the intermediate values the construction produces on the way. This is the AEAD that TLS 1.3, WireGuard, SSH and age all use, and the one you reach for when there is no AES hardware to lean on — ChaCha20 is additions, XORs and rotations, so it runs at a predictable speed on anything, and it has no lookup tables to leak through a cache. The construction is two primitives glued together in a way that is easy to get slightly wrong by hand, which is why the internals are on screen. Counter 0 of the ChaCha20 stream is not used for data at all: its first 32 bytes become the one-time Poly1305 key, and the keystream for the plaintext starts at counter 1. Off-by-one there produces something that encrypts and decrypts consistently with itself and is incompatible with every other implementation. The MAC then covers the additional data, the ciphertext, and both of their lengths as 64-bit little-endian values, each of the first two padded to a 16-byte boundary — leave the padding or the lengths out and tags verify for messages the sender never authorised. The r half of the Poly1305 key is clamped before use, and that too is shown. Decryption here refuses to hand back a plaintext when the tag does not verify, which is the property that separates an AEAD from a cipher with a checksum bolted on. The tool also tracks key and nonce pairs within the tab: encrypting two different messages under one pair reveals the XOR of the plaintexts and leaks the Poly1305 key, after which tags can be forged at will, so it says so loudly rather than letting it pass.
Frequently asked questions
Why does the keystream start at counter 1?
Because counter 0 is spent making the Poly1305 key. The AEAD calls the ChaCha20 block function once with a counter of zero and takes the first 32 bytes of that block as a one-time authentication key, then encrypts the plaintext with the stream starting at counter 1. An implementation that starts the data at 0 is self-consistent and interoperates with nothing.
What happens if I reuse a nonce?
Two messages under one key and nonce give an attacker the XOR of the plaintexts, which is often enough on its own. Worse, both messages share the same one-time Poly1305 key, and seeing two valid tags under one such key is enough to recover it — after which the attacker can forge tags for messages of their choosing. This is not a degradation, it is a break, and it is why the tool warns.
Why are the lengths in the MAC input?
Without them the boundary between the additional data and the ciphertext is ambiguous, and an attacker can move bytes from one to the other while keeping the tag valid. The construction appends the AAD length and the ciphertext length as 64-bit little-endian integers, after padding each of the two parts to a multiple of 16, precisely to pin that boundary down.
How does this compare with AES-GCM?
Both are AEADs with a 16-byte tag and a 12-byte nonce, and both fail catastrophically on nonce reuse. AES-GCM is faster where AES instructions exist and slower and more side-channel-prone where they do not; ChaCha20-Poly1305 is uniformly quick in software and has no table lookups. GCM also degrades if you truncate its tag, while Poly1305 has one tag length. For new protocols either is defensible; on mobile and embedded targets ChaCha20-Poly1305 usually wins.
Is this safe to use for real secrets?
The arithmetic is checked against every test vector in RFC 8439 and against a second implementation, but that is not the same as being safe to deploy. It runs in a browser tab, in JavaScript, with no constant-time guarantees and with your key in a text field and in this page’s local storage. Use it to check an implementation or to understand the construction, and use a reviewed library for anything that matters.
Related tools
AES-GCM Encrypt / Decrypt (key, nonce, AAD)
Encrypt and decrypt with AES-GCM in your browser: hex key and nonce, optional AAD, selectable tag length, and the ciphertext and tag kept apart.
Developer
TLS Cipher Suite Decoder
Paste an IANA cipher suite name and get its key exchange, authentication, bulk cipher, mode and MAC — plus a security grade for forward secrecy and AEAD.
Network
OCSP Response & Request Decoder
Decode an OCSP response or request in your browser: status, responder, freshness, nonce, revocation reason and the certificates it carries.
Developer
DNSSEC Calculator — DS Record & NSEC3 Hash
Turn a DNSKEY into the DS record your registrar wants — key tag and all three digest types — or hash a name the way NSEC3 does.
Network
Ed25519 Sign & Verify (RFC 8032)
Sign a message with an Ed25519 key or verify a signature in the browser, with the public key derived from the seed and R and S shown.
Developer
Argon2 Hash Generator & Verifier (Argon2id)
Hash a password with Argon2id, Argon2i or Argon2d and get the $argon2id$ PHC string, or check a password against one. Runs in your browser.
Developer