NAME
Crypt::Sodium::XS::scalarmult - Point-scalar multiplication on the Curve25519 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 Curve25519 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
The constructor is called with the Crypt::Sodium::XS->scalarmult method.
my $scalarmult = Crypt::Sodium::XS->scalarmult;
my $scalarmult = Crypt::Sodium::XS->scalarmult(primitive => 'x25519');
Returns a new scalarmult object.
Implementation detail: the returned object is blessed into Crypt::Sodium::XS::OO::scalarmult.
ATTRIBUTES
primitive
my $primitive = $scalarmult->primitive;
$scalarmult->primitive('poly1305');
Gets or sets the primitive used for all operations by this object. It must be one of the primitives listed in "PRIMITIVES", including default.
METHODS
primitives
my @primitives = $scalarmult->primitives;
my @primitives = Crypt::Sodium::XS::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.
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>.
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);
PRIMITIVES
- x25519 (default)
-
X25519 (ECDH over Curve25519). See RFC 7748.
- ed25519
-
Low-level edwards25519 curve. Only to be used for creating custom constructions.
- ristretto255
-
Ristretto is a new unified point compression format for curves over large-characteristic fields, which divides the curve’s cofactor by 4 or 8 at very little cost of performance, efficiently implementing a prime-order group.
libsodium 1.0.18+ implements ristreto255: ristretto on top of the Curve25519 curve.
Compared to Curve25519 points encoded as their coordinates, ristretto makes it easier to safely implement protocols originally designed for prime-order groups.
FUNCTIONS
The object API above is the recommended way to use this module. The functions and constants documented below can be imported instead or in addition.
Nothing is exported by default. A :default tag imports the functions and constants documented below. A separate :<primitive> import tag is provided for each of the primitives listed in "PRIMITIVES". These tags import the scalarmult_<primitive>_* functions and constants for that primitive. A :all tag imports everything.
scalarmult_base
scalarmult_<primitive>_base
my $public_key = scalarmult_base($secret_key);
Same as "base".
scalarmult
scalarmult_<primitive>
my $shared_secret = scalarmult($my_secret_key, $their_public_key);
Same as "scalarmult".
scalarmult_keygen
scalarmult_<primitive>_keygen
my $secret_key = scalarmult_keygen();
Same as "keygen".
scalarmult_ed25519_base_noclamp
my $q_noclamp = scalarmult_ed25519_base_noclamp($n);
Same as "base_noclamp".
scalarmult_ed25519_noclamp
my $q_noclamp = scalarmult_ed25519_noclamp($n, $p);
Same as "scalarmult_noclamp".
CONTSANTS
"scalarmult_BYTES" and "scalarmult_SCALARBYTES" are provided for consistency, but it is safe to assume that scalarmult_BYTES == scalarmult_SCALARBYTES.
scalarmult_BYTES
scalarmult_<primitive>_BYTES
my $public_key_size = scalarmult_BYTES();
Same as "BYTES".
scalarmult_SCALARBYTES
scalarmult_<primitive>_SCALARBYTES
my $shared_and_secret_key_size = scalarmult_SCALARBYTES();
Same as "SCALARBYTES".
SEE ALSO
- Crypt::Sodium::XS
- https://doc.libsodium.org/advanced/scalar_multiplication
- https://doc.libsodium.org/advanced/point-arithmetic
-
See 'Scalar Multiplication' for ed25519.
FEEDBACK
For reporting bugs, giving feedback, submitting patches, etc. please use the following:
RT queue at https://rt.cpan.org/Dist/Display.html?Name=Crypt-Sodium-XS
IRC channel
#sodiumonirc.perl.org.Email the author directly.
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.