Security Advisories (2)
CVE-2025-15444 (2026-01-06)

Crypt::Sodium::XS module versions prior to 0.000042, for Perl, include a vulnerable version of libsodium libsodium <= 1.0.20 or a version of libsodium released before December 30, 2025 contains a vulnerability documented as CVE-2025-69277  https://www.cve.org/CVERecord?id=CVE-2025-69277 . The libsodium vulnerability states: In atypical use cases involving certain custom cryptography or untrusted data to crypto_core_ed25519_is_valid_point, mishandles checks for whether an elliptic curve point is valid because it sometimes allows points that aren't in the main cryptographic group. 0.000042 includes a version of libsodium updated to 1.0.20-stable, released January 3, 2026, which includes a fix for the vulnerability.

CVE-2026-30910 (2026-03-08)

Crypt::Sodium::XS versions through 0.001000 for Perl has potential integer overflows. Combined aead encryption, combined signature creation, and bin2hex functions do not check that output size will be less than SIZE_MAX, which could lead to integer wraparound causing an undersized output buffer. This can cause a crash in bin2hex and encryption algorithms other than aes256gcm. For aes256gcm encryption and signatures, an undersized buffer could lead to buffer overflow. Encountering this issue is unlikely as the message length would need to be very large. For bin2hex the input size would have to be > SIZE_MAX / 2 For aegis encryption the input size would need to be > SIZE_MAX - 32U For other encryption the input size would need to be > SIZE_MAX - 16U For signatures the input size would need to be > SIZE_MAX - 64U

NAME

Crypt::Sodium::XS::OO::scalarmult - Point-scalar multiplication over the edwards25519 curve

SYNOPSIS

use Crypt::Sodium::XS 'sodium_random_bytes';
my $scalarmult = Crypt::Sodium::XS->scalarmult;

my $keysize = Crypt::Sodium::XS->box->SECRETKEYBYTES;
my $client_sk = sodium_random_bytes($keysize);
my $client_pk = $scalarmult->base($client_sk);
my $server_sk = sodium_random_bytes($keysize);
my $server_pk = $scalarmult->base($client_sk);

# !!! do not use output directly as key exchange !!!
# use Crypt::Sodium::XS::kx instead, or you can extract shared keys of
# arbitrary size with generichash:

# client side:
my $client_shared_secret = $scalarmult->scalarmult($client_sk, $server_pk);
my $hasher = Crypt::Sodium::XS->generichash->init;
$hasher->update($shared_secret, $client_pk, $server_pk);
my $client_shared_key = $hasher->final;

# server side:
my $server_shared_secret = $scalarmult->scalarmult($server_sk, $client_pk);
my $hasher = Crypt::Sodium::XS->generichash->init;
$hasher->update($shared_secret, $client_pk, $server_pk);
my $server_shared_key = $hasher->final;

DESCRIPTION

Crypt::Sodium::XS::scalarmult provides an API to multiply a point on the edwards25519 curve.

This can be used as a building block to construct key exchange mechanisms, or more generally to compute a public key from a secret key. For key exchange, you generally want to use Crypt::Sodium::XS::kx instead.

CONSTRUCTOR

new

my $scalarmult
  = Crypt::Sodium::XS::OO::scalarmult->new(primitive => 'x25519');
my $scalarmult = Crypt::Sodium::XS->scalarmult;

Returns a new scalarmult object for the given primitive. If not given, the default primitive is default.

ATTRIBUTES

primitive

my $primitive = $scalarmult->primitive;
$scalarmult->primitive('poly1305');

Gets or sets the primitive used for all operations by this object. Note this can be default.

METHODS

primitives

my @primitives = Crypt::Sodium::XS::OO::scalarmult->primitives;
my @primitives = $scalarmult->primitives;

Returns a list of all supported primitive names, including default.

Can be called as a class method.

PRIMITIVE

my $primitive = $scalarmult->PRIMITIVE;

Returns the primitive used for all operations by this object. Note this will never be default but would instead be the primitive it represents.

keygen

my $secret_key = $scalarmult->keygen;

Returns a Crypt::Sodium::XS::MemVault: a secret key of "SCALARBYTES" bytes.

base

my $public_key = $scalarmult->base($secret_key);

$secret_key is a secret key. It must be "SCALARBYTES" bytes. It may be a Crypt::Sodium::XS::MemVault.

Returns a public key which is "BYTES" bytes.

Multiplies the base point (x, 4/5) by a scalar $secret_key (clamped) and returns the Y coordinate of the resulting point.

NOTE: With the ed25519 primitive, a $secret_key of 0 will croak.

scalarmult

my $q = $scalarmult->scalarmult($my_secret_key, $their_public_key);

$my_secret_key is a secret key. It must be "SCALARBYTES" bytes. It may be a Crypt::Sodium::XS::MemVault.

$their_public_key is a public key. It must be "BYTES" bytes.

Returns a Crypt::Sodium::XS::MemVault: a shared secret of "SCALARBYTES" bytes.

Note (ed25519):

With the ed25519 primitive, this function will croak if $my_secret_key is 0 or if $their_public_key is not on the curve, not on the main subgroup, is a point of small order, or is not provided in canonical form.

Also with ed25519, $my_secret_key is “clamped” (the 3 low bits are cleared to make it a multiple of the cofactor, bit 254 is set and bit 255 is cleared to respect the original design).

Note:

$q represents the X coordinate of a point on the curve. As a result, the number of possible keys is limited to the group size (≈2^252), which is smaller than the key space.

For this reason, and to mitigate subtle attacks due to the fact many (p, n) pairs produce the same result, using the output of the multiplication q directly as a shared key is not recommended.

A better way to compute a shared key is h(q | pk1 | pk2), with pk1 and pk2 being the public keys.

By doing so, each party can prove what exact public key they intended to perform a key exchange with (for a given public key, 11 other public keys producing the same shared secret can be trivially computed).

See "SYNOPSIS" for an example of this.

SCALAR MULTIPLICATION WITHOUT CLAMPING

In order to prevent attacks using small subgroups, the scalarmult methods above clear lower bits of the scalar ($secret_key). This may be indesirable to build protocols that require $secret_key to be invertible.

The noclamp variants of these functions do not clear these bits, and do not set the high bit either. These variants expect a scalar in the ]0..L[ range.

These methods are only available for the ed25519 primitive.

scalarmult_base_noclamp

my $q_noclamp = $scalarmult->base_noclamp($n);

scalarmult_noclamp

my $q_noclamp = $scalarmult->scalarmult_noclamp($n, $p);

BYTES

my $out_size = $scalarmult->BYTES

Returns the size, in bytes, of a public key.

SCALARBYTES

Returns the size, in bytes, of a shared or secret key.

my $out_size = $scalarmult->SCALARBYTES

"BYTES" and "SCALARBYTES" are provided for consistency, but it is safe to assume that $scalarmult-BYTES == $scalarmult->SCALARBYTES>.

SEE ALSO

Crypt::Sodium::XS
Crypt::Sodium::XS::scalarmult
https://doc.libsodium.org/advanced/scalar_multiplication

FEEDBACK

For reporting bugs, giving feedback, submitting patches, etc. please use the following:

For any security sensitive reports, please email the author directly or contact privately via IRC.

AUTHOR

Brad Barden <perlmodules@5c30.org>

COPYRIGHT & LICENSE

Copyright (c) 2022 Brad Barden. All rights reserved.

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