Security Advisories (2)
CVE-2026-2588 (2026-02-22)

Crypt::NaCl::Sodium versions through 2.001 for Perl has an integer overflow flaw on 32-bit systems. Sodium.xs casts a STRLEN (size_t) to unsigned long long when passing a length pointer to libsodium functions. On 32-bit systems size_t is typically 32-bits while an unsigned long long is at least 64-bits.

CVE-2026-30909 (2026-03-08)

Crypt::NaCl::Sodium versions through 2.002 for Perl has potential integer overflows. bin2hex, encrypt, aes256gcm_encrypt_afternm and seal functions do not check that output size will be less than SIZE_MAX, which could lead to integer wraparound causing an undersized output buffer. Encountering this issue is unlikely as the message length would need to be very large. For bin2hex() the bin_len would have to be > SIZE_MAX / 2 For encrypt() the msg_len would need to be > SIZE_MAX - 16U For aes256gcm_encrypt_afternm() the msg_len would need to be > SIZE_MAX - 16U For seal() the enc_len would need to be > SIZE_MAX - 64U

NAME

Crypt::NaCl::Sodium::secretbox - Secret-key authenticated encryption

SYNOPSIS

use Crypt::NaCl::Sodium qw( :utils );

my $crypto_secretbox = Crypt::NaCl::Sodium->secretbox();

my ($key, $nonce, $decrypted_msg, $msg, $secret);

## Alice
########

# Alice generates secret key
$key = $crypto_secretbox->keygen();

# ... and shares it with Bob
send_to( Bob => { key => $key } );

# now Alice and Bob can start communicating

# Alice generates random nonce
$nonce = $crypto_secretbox->nonce();

send_to( Bob => { nonce => $nonce } );

# Alice's message to Bob
$msg = "Hi Bob!";

# encrypts using combined mode
$secret = $crypto_secretbox->encrypt( $msg, $nonce, $key );

# message is ready for Bob
send_to( Bob => { secret => $secret } );

## Bob
########

# Bob receives the secret key from Alice
$key = receive_for( Bob => 'key' );

# and random nonce
$nonce = receive_for( Bob => 'nonce' );

# Bob is now ready to receive first message from Alice
$secret = receive_for( Bob => 'secret' );

# we have now all information required to decrypt message
$decrypted_msg = $crypto_secretbox->decrypt( $secret, $nonce, $key );

# time to reply
$msg = "Hello Alice!";

# generates new nonce
$nonce = $crypto_secretbox->nonce();

# this time we use detached mode
($mac, $secret) = $crypto_secretbox->encrypt( $msg, $nonce, $key );

# Alice needs all pieces to verify and decrypt Bob's message
send_to( Alice => { nonce => $nonce } );
send_to( Alice => { mac => $mac } );
send_to( Alice => { secret => $secret } );

## Alice
########

# Bob used the detached mode
$nonce  = receive_for( Alice => 'nonce' );
$mac    = receive_for( Alice => 'mac' );
$secret = receive_for( Alice => 'secret' );

# we have now all information required to decrypt message
$decrypted_msg = $crypto_secretbox->decrypt_detached( $mac, $secret, $nonce, $key );

# NOTE: send_to() and receive_for() and user functions providing transport of
# messages

DESCRIPTION

Secret-key (also known as symmetric-key) cryptography can be compared to combination lock safe - only those who know the correct lock code can open it.

Therefore the generated key must be distributed in secret.

Nonce (number used once) does not have to be protected, but it is crucial that the same nonce has not been ever reused with the same key.

The authentication tag confirms that the encrypted data has not been tampered with before decrypting it.

METHODS

keygen

my $key = $crypto_secretbox->keygen();

Helper method to generate a random key to be used by $crypto_secretbox.

The length of the $key equals "KEYBYTES".

NOTE: keep the key confidential.

Returns Data::BytesLocker object.

nonce

my $nonce = $crypto_secretbox->nonce();

Helper method to generate a random nonce to be used by $crypto_secretbox.

The length of the nonce equals "NONCEBYTES".

If initial value has been passed as the argument, it will then padded with null bytes.

my $counter = 121;
my $nonce = $crypto_secretbox->nonce($counter);
$nonce =~ /^121\0+$/ or die;

NOTE: nonce does not have to be random nor confidential, but it must never be reused with the same key. It is large enough that the randomly generated nonces have negligible risk of collision.

If random nonce is being used it needs to be provided to the other party to allow decryption.

If counter is being used store it alongside the key to avoid accidental reuse on the next session. In connection-oriented protocols counter-based nonce could help rejecting duplicate messages.

Returns Data::BytesLocker object.

encrypt

# combined mode - MAC and encrypted message stored together
my $secret = $crypto_secretbox->encrypt($msg, $nonce, $key);

# detached mode - MAC and encrypted message returned separate
my ($mac, $ciphertext) = $crypto_secretbox->encrypt($msg, $nonce, $key);

Encrypts the plaintext message using given $nonce and $key.

In scalar context works in combined mode, where MAC and encrypted message are stored together. The length of the $secret is equal to the length of $msg + "MACBYTES".

In list context the $mac and $ciphertext are returned separately. The length of the $ciphertext is equal to the length of $msg, while length of $mac is "MACBYTES".

Returns Data::BytesLocker object.

decrypt

my $msg;
eval {
    $msg = $crypto_secretbox->decrypt($secret, $nonce, $key);
};
if ( $@ ) {
    warn "Message forged!";
} else {
    print "Decrypted message: $msg\n";
}

Verifies and decrypts the secret message using given $nonce and $key.

Function croaks if the verification fails. Otherwise returns the decrypted message.

The length of the $msg is equal to the length of $secret - "MACBYTES".

Returns Data::BytesLocker object.

decrypt_detached

my $msg;
eval {
    $msg = $crypto_secretbox->decrypt_detached($mac, $ciphertext, $nonce, $key);
};
if ( $@ ) {
    warn "Message forged!";
} else {
    print "Decrypted message: $msg\n";
}

Verifies and decrypts the secret message $ciphertext authenticated with $mac using given $nonce and $key.

Function croaks if the verification fails. Otherwise returns the decrypted message.

The length of the $msg equals the length of $ciphertext.

Returns Data::BytesLocker object.

CONSTANTS

NONCEBYTES

my $nonce_length = $crypto_secretbox->NONCEBYTES;

Returns the length of nonce.

KEYBYTES

my $key_length = $crypto_secretbox->KEYBYTES;

Returns the length of key.

MACBYTES

my $mac_length = $crypto_secretbox->MACBYTES;

Returns the length of MAC.

ALGORITHM DETAILS

crypto_secretbox for encryption uses XSalsa20 stream cipher (which is based on Salsa20, but with much longer nonce) and Poly1305 MAC for authentication.

SEE ALSO

AUTHOR

Alex J. G. Burzyński <ajgb@cpan.org>

COPYRIGHT & LICENSE

Copyright (c) 2015 Alex J. G. Burzyński. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.