O modo CTR transforma o AES numa cifra de fluxo; para decifrar, é preciso a chave e o contador inicial exato.
O AES cifra blocos de 16 bytes. No modo CTR (counter), ele não cifra a mensagem: cifra um contador (16 bytes que começam num valor inicial, o IV ou nonce, e sobem de 1 em 1 a cada bloco) e faz XOR do resultado com a mensagem. Cifrar e decifrar são a mesma operação.
bloco cifrado i = mensagem i XOR AES(chave, contador inicial + i)
No modo CTR, o AES cifra o contador (IV, IV + 1, IV + 2) e o resultado faz XOR com cada bloco da mensagem; o último bloco fica do tamanho que tiver, sem preenchimento.
Duas consequências práticas:
O cifrado tem o mesmo tamanho da mensagem, sem preenchimento.
Para decifrar, não basta a chave: o contador inicial tem de ser exatamente o mesmo, byte por byte. Com o contador errado, sai lixo, sem nenhum erro avisando. Cada sistema monta esse contador do seu jeito (o id do pacote, o remetente, zeros), e essa receita faz parte do protocolo.
Em Python, com pycryptodome:
from Crypto.Cipher import AES
AES.new(chave, AES.MODE_CTR, nonce=b"", initial_value=iv16).decrypt(cifrado)
No CyberChef (abre em nova aba), AES Decrypt com o modo CTR, a chave e o IV em hexadecimal. Chave de 16 bytes é AES-128; de 32, AES-256. Reusar o mesmo contador com a mesma chave em duas mensagens é um erro grave: o XOR dos dois cifrados é o XOR das duas mensagens.