Crypt::Mode::CTR(3)

πŸ’œ Crypt::Mode::CTR β€” the perl manual page, bestie edition πŸ’œ

okay so you're reading the Crypt::Mode::CTR(3) page (yes that's the manual name, we're not copying the header line, we're folding it in like a good little intro, you're welcome 🫢). It's about CTR mode, aka Counter mode, and it is so useful. Sit down, hydrate, let's go ✨


✨ NAME ✨

Crypt::Mode::CTR β€” Block cipher mode CTR [Counter mode]. That's it, that's the whole name. Short, iconic, to the point πŸ’…


🌸 SYNOPSIS 🌸

here's the whole vibe in code, no notes:

use Crypt::Mode::CTR;
my $m = Crypt::Mode::CTR->new('AES');
my $key = '1234567890123456';
my $iv = '1234567890123456';
my $plaintext = 'example plaintext';
my $chunk1 = 'example ';
my $chunk2 = 'plaintext';

# encrypt or decrypt in one call
my $single_ciphertext = $m->encrypt($plaintext, $key, $iv);
my $single_plaintext = $m->decrypt($single_ciphertext, $key, $iv);

# encrypt more chunks
$m->start_encrypt($key, $iv);
my $chunked_ciphertext = '';
$chunked_ciphertext .= $m->add($chunk1);
$chunked_ciphertext .= $m->add($chunk2);

# decrypt more chunks
$m->start_decrypt($key, $iv);
my $chunked_plaintext = '';
$chunked_plaintext .= $m->add($chunked_ciphertext);

like… one call or many chunks, both slay πŸ’–


πŸ¦‹ DESCRIPTION πŸ¦‹

So this module implements CTR cipher mode. That's the whole thing. But there's a catch, bestie, and it's a big one:

⚠️ Note: it works only with ciphers from CryptX (Crypt::Cipher::NNNN). Don't show up with some random other cipher, it's not gonna work, ngl.

πŸŽ€ METHODS πŸŽ€

Unless noted otherwise, assume $m is an existing mode object created via "new", for example:

my $m = Crypt::Mode::CTR->new('AES');

like, that's your main character. everything below is done to $m. periodt πŸ‘‘


πŸ’« new

okay so this is where it all begins. three flavors of constructor, pick your fighter:

my $m = Crypt::Mode::CTR->new($cipher_name);
#or
my $m = Crypt::Mode::CTR->new($cipher_name, $ctr_mode, $ctr_width);
#or
my $m = Crypt::Mode::CTR->new($cipher_name, $ctr_mode, $ctr_width, $cipher_rounds);

# $cipher_name .. [string] one of 'AES', 'Anubis', 'Blowfish', 'CAST5', 'Camellia', 'DES', 'DES_EDE',
#                 'KASUMI', 'Khazad', 'MULTI2', 'Noekeon', 'RC2', 'RC5', 'RC6',
#                 'SAFERP', 'SAFER_K128', 'SAFER_K64', 'SAFER_SK128', 'SAFER_SK64',
#                 'SEED', 'Skipjack', 'Twofish', 'XTEA', 'IDEA', 'Serpent'
#                 or any <NAME> for which there is a Crypt::Cipher::<NAME> module
# $ctr_mode ..... [integer] CTR_COUNTER_LITTLE_ENDIAN    (0) - little-endian counter (DEFAULT)
#                 CTR_COUNTER_BIG_ENDIAN       (1) - big-endian counter
#                 CTR_COUNTER_LITTLE_ENDIAN | 2 (2) - little-endian + RFC 3686 initial-counter-incrementing
#                 CTR_COUNTER_BIG_ENDIAN | 2    (3) - big-endian + RFC 3686 initial-counter-incrementing
# $ctr_width .... [integer] counter width in bytes (DEFAULT = full block width, e.g. 16 for AES)
# $cipher_rounds ... [integer] optional, number of rounds for given cipher

bestie look at that cipher list. 'AES', 'Anubis', 'Blowfish', 'CAST5', 'Camellia', 'DES', 'DES_EDE', 'KASUMI', 'Khazad', 'MULTI2', 'Noekeon', 'RC2', 'RC5', 'RC6', 'SAFERP', 'SAFER_K128', 'SAFER_K64', 'SAFER_SK128', 'SAFER_SK64', 'SEED', 'Skipjack', 'Twofish', 'XTEA', 'IDEA', 'Serpent' β€” or literally any <NAME> that has a Crypt::Cipher::<NAME> module. so many icons, all valid 🌈

And the $ctr_mode values, spelled out with their numbers so you can't mess it up:

  • CTR_COUNTER_LITTLE_ENDIAN (0) β€” little-endian counter. this is the DEFAULT πŸ’–
  • CTR_COUNTER_BIG_ENDIAN (1) β€” big-endian counter
  • CTR_COUNTER_LITTLE_ENDIAN | 2 (2) β€” little-endian plus RFC 3686 initial-counter-incrementing
  • CTR_COUNTER_BIG_ENDIAN | 2 (3) β€” big-endian plus RFC 3686 initial-counter-incrementing

$ctr_width is [integer] β€” counter width in bytes, and the DEFAULT = full block width (so like 16 for AES, iykyk).

$cipher_rounds is [integer], optional β€” number of rounds for the given cipher.


πŸ”₯ encrypt

Encrypts the plaintext in a single call. Returns the ciphertext as a binary string. easy.

But here's the tea on how the scalar gets handled πŸ“: the plaintext scalar is converted to bytes using Perl's usual scalar stringification. Defined scalars β€” including numbers and string-overloaded objects β€” are accepted. undef is treated as an empty string and may emit Perl's usual "uninitialized value" warning. so like, defined scalars only, unless you want the warning, in which case, live your truth 😭

my $ciphertext = $m->encrypt($plaintext, $key, $iv);

🌟 decrypt

Decrypts the ciphertext in a single call. Returns the plaintext as a binary string.

Same deal as encrypt, fr fr: the ciphertext scalar is converted to bytes using Perl's usual scalar stringification. Defined scalars, including numbers and string-overloaded objects, are accepted. undef is treated as an empty string and may emit Perl's usual "uninitialized value" warning.

my $plaintext = $m->decrypt($ciphertext, $key, $iv);

πŸ’… start_encrypt

Initializes encryption mode. Returns the object itself (so it chains, cute).

$m->start_encrypt($key, $iv);

🧚 start_decrypt

Initializes decryption mode. Returns the object itself (same energy).

$m->start_decrypt($key, $iv);

⭐ add

Feeds data to the encryption or decryption stream. Returns a binary string. this is the streaming girlie of the family πŸ’œ

Every argument is converted to bytes using Perl's usual scalar stringification. Defined scalars, including numbers and string-overloaded objects, are accepted. undef is treated as an empty string and may emit Perl's usual "uninitialized value" warning. (yes, same warning discourse, we've been over this πŸ™ˆ)

# in encrypt mode
my $ciphertext = $m->add($plaintext);

# in decrypt mode
my $plaintext = $m->add($ciphertext);

πŸŽ€ finish

okay so this is lowkey the funniest one: CTR is a streaming mode and does not use padding, so "finish" returns an empty string. It exists purely for API consistency with Crypt::Mode::CBC and Crypt::Mode::ECB, and may be safely called or omitted. it's giving "I'm here for moral support" πŸ’€

$m->start_encrypt($key, $iv);
my $ciphertext = '';
$ciphertext .= $m->add($chunk1);
$ciphertext .= $m->add($chunk2);
$ciphertext .= $m->finish;   # returns ''

πŸ‘‘ SEE ALSO πŸ‘‘


okay that's the whole page, you're officially edu-macated πŸŽ“βœ¨

and for the cute sign-off: this glorious thing is perl v5.42.0, dated 2026-05-11, and it's the Crypt::Mode::CTR(3) manpage β€” go forth and encrypt responsibly, bestie πŸ’–πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from